aboutsummaryrefslogtreecommitdiffstats
path: root/lint/cli
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-12-07 15:59:22 -0800
committerTor Norbye <tnorbye@google.com>2012-12-07 15:59:22 -0800
commitb2610dc727355ff1fb22144226c7c47f42f4b636 (patch)
tree0138ac74b4eabc94d0807fd97604a3021e4d41a6 /lint/cli
parent3843919d1561e98d9bf66193e0e68c7ae30db4dd (diff)
downloadsdk-b2610dc727355ff1fb22144226c7c47f42f4b636.zip
sdk-b2610dc727355ff1fb22144226c7c47f42f4b636.tar.gz
sdk-b2610dc727355ff1fb22144226c7c47f42f4b636.tar.bz2
Move lint unit tests into lint/cli
The unit tests for lint have lived in the lint/libs/lint_checks library, but that's not a natural place since the cli library depends on the lint_checks library, yet the lint_check *tests* also depend on cli. Furthermore, the tests also test stuff in the cli library. Thus, move the test sources over to the cli library, which also pulls in the lint_checks library. Change-Id: Ia8527ea894b287915ad12c04c16daf80ace67bdc
Diffstat (limited to 'lint/cli')
-rw-r--r--lint/cli/Android.mk13
-rw-r--r--lint/cli/src/test/.classpath19
-rw-r--r--lint/cli/src/test/.project17
-rw-r--r--lint/cli/src/test/.settings/org.eclipse.core.resources.prefs5
-rw-r--r--lint/cli/src/test/.settings/org.moreunit.prefs4
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/LintCliXmlParserTest.java162
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/MainTest.java301
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/XmlReporterTest.java244
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/AbstractCheckTest.java442
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/AccessibilityDetectorTest.java43
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/AlwaysShowActionDetectorTest.java85
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/AnnotationDetectorTest.java66
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java719
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ApiLookupTest.java211
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ArraySizeDetectorTest.java71
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ButtonDetectorTest.java415
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ChildCountDetectorTest.java44
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ColorUsageDetectorTest.java44
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/CommentDetectorTest.java53
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/CutPasteDetectorTest.java55
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/DeprecationDetectorTest.java87
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/DetectMissingPrefixTest.java84
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/DosLineEndingDetectorTest.java49
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/DuplicateIdDetectorTest.java91
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/DuplicateResourceDetectorTest.java63
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ExtraTextDetectorTest.java37
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/FieldGetterDetectorTest.java135
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/FragmentDetectorTest.java61
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/GridLayoutDetectorTest.java37
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/HandlerDetectorTest.java46
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/HardcodedDebugModeDetectorTest.java43
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/HardcodedValuesDetectorTest.java73
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/IconDetectorTest.java460
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/InefficientWeightDetectorTest.java127
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/InvalidPackageDetectorTest.java56
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/JavaPerformanceDetectorTest.java98
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/LabelForDetectorTest.java78
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/LocaleDetectorTest.java76
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ManifestOrderDetectorTest.java277
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/MathDetectorTest.java67
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/MergeRootFrameLayoutDetectorTest.java69
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/MissingClassDetectorTest.java270
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/MissingIdDetectorTest.java37
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/NamespaceDetectorTest.java183
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/NestedScrollingWidgetDetectorTest.java37
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/NonInternationalizedSmsDetectorTest.java38
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ObsoleteLayoutParamsDetectorTest.java104
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/OnClickDetectorTest.java75
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/OverdrawDetectorTest.java102
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/OverrideDetectorTest.java47
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/PrivateKeyDetectorTest.java43
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/PrivateResourceDetectorTest.java37
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ProguardDetectorTest.java93
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/PxUsageDetectorTest.java89
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/RegistrationDetectorTest.java131
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/RequiredAttributeDetectorTest.java125
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ScrollViewChildDetectorTest.java37
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/SdCardDetectorTest.java98
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/SecureRandomDetectorTest.java64
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/SecurityDetectorTest.java265
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/SetJavaScriptEnabledDetectorTest.java38
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/SharedPrefsDetectorTest.java109
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/StateListDetectorTest.java55
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/StringFormatDetectorTest.java179
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/StyleCycleDetectorTest.java49
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/SystemPermissionsDetectorTest.java300
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/TextFieldDetectorTest.java127
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/TextViewDetectorTest.java102
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/TitleDetectorTest.java58
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ToastDetectorTest.java47
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/TooManyViewsDetectorTest.java47
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/TranslationDetectorTest.java212
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/TypoDetectorTest.java155
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/TypoLookupTest.java523
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/TypographyDetectorTest.java140
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/UnusedResourceDetectorTest.java266
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java51
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/UselessViewDetectorTest.java67
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/Utf8DetectorTest.java56
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ViewConstructorDetectorTest.java64
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ViewTagDetectorTest.java68
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ViewTypeDetectorTest.java85
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/WakelockDetectorTest.java160
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/WrongIdDetectorTest.java98
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/WrongImportDetectorTest.java40
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/WrongLocationDetectorTest.java43
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/AbstractActivity.java.txt6
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/AndroidManifest.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/allowbackup.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/allowbackup_ignore.xml25
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest.class.databin0 -> 1750 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest.java.txt52
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.class.databin0 -> 1292 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.java.txt45
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11$MyActivity.class.databin0 -> 566 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11$MyLinear.class.databin0 -> 810 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11.class.databin0 -> 872 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11.java.txt50
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest12.class.databin0 -> 1044 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest12.java.txt30
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest2.class.databin0 -> 386 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest2.java.txt9
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest3.class.databin0 -> 409 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest3.java.txt12
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$1.class.databin0 -> 674 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$InnerClass1$InnerInnerClass1.class.databin0 -> 762 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$InnerClass1.class.databin0 -> 824 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$InnerClass2.class.databin0 -> 638 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4.class.databin0 -> 854 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4.java.txt41
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest5.class.databin0 -> 796 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest5.java.txt23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest6.class.databin0 -> 512 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest6.java.txt10
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest7.class.databin0 -> 596 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest7.java.txt14
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest8.class.databin0 -> 426 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest8.java.txt10
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.class.databin0 -> 732 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.java.txt19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest$LocalClass.class.databin0 -> 798 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest.class.databin0 -> 887 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest.java.txt42
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2$1$1.class.databin0 -> 704 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2$1$2.class.databin0 -> 704 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2$1.class.databin0 -> 1059 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2.class.databin0 -> 556 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2.java.txt39
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/CloseTest.class.databin0 -> 511 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/CloseTest.java.txt9
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate$IntermediateCustomV.class.databin0 -> 440 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate.class.databin0 -> 383 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate.java.txt15
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest1.class.databin0 -> 2775 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest1.java.txt137
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest2.class.databin0 -> 898 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest2.java.txt25
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest3.class.databin0 -> 901 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest3.java.txt25
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest4.class.databin0 -> 550 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest4.java.txt21
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestEnum.class.databin0 -> 4940 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestEnum.java.txt67
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestLint.class.databin0 -> 829 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/classpath8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/colors.xml6
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/holomanifest.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/layout.xml32
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/layout_targetapi.xml35
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk1.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk10.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk14.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk17.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk2.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk4.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/themes.xml16
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/unsupported.jar.databin0 -> 1196 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/view.xml27
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/broken-manifest.xml18
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/broken-manifest2.xml28
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/.classpath8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AbstractActivity.class.databin0 -> 295 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AbstractActivity.java.txt6
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AndroidManifest.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AndroidManifestReg.xml18
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AndroidManifestWrongRegs.xml21
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class1$Class4.class.databin0 -> 368 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class1.class.databin0 -> 812 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class2$Class3.class.databin0 -> 457 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class2.class.databin0 -> 942 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CommentsActivity.class.databin0 -> 303 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CommentsActivity.java.txt6
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView1.class.databin0 -> 313 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView1.java.txt9
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView2.class.databin0 -> 543 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView2.java.txt12
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView3.class.databin0 -> 736 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView3.java.txt20
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomViewTest.class.databin0 -> 390 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment1.class.databin0 -> 373 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment2.class.databin0 -> 460 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment3.class.databin0 -> 377 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment4.class.databin0 -> 406 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment5.class.databin0 -> 471 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment6.class.databin0 -> 487 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$NotAFragment.class.databin0 -> 465 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$ValidFragment1.class.databin0 -> 392 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest.class.databin0 -> 774 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest.java.txt55
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.class.databin0 -> 1291 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.jar.databin0 -> 1298 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.java.txt59
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest$1.class.databin0 -> 629 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest$Inner.class.databin0 -> 599 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest$StaticInner.class.databin0 -> 532 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest.class.databin0 -> 607 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest.java.txt24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/LocaleTest.class.databin0 -> 2272 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/LocaleTest.java.txt37
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/MathTest.class.databin0 -> 847 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/MathTest.java.txt21
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/OnClickActivity.class.databin0 -> 1282 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/OnClickActivity.java.txt48
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/SecureRandomTest.class.databin0 -> 1379 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/SecureRandomTest.java.txt42
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestFieldGetter.class.databin0 -> 933 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestFieldGetter.java.txt36
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider.class.databin0 -> 1401 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider.java.txt40
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider2.class.databin0 -> 287 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider2.java.txt4
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver$1.class.databin0 -> 748 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver.class.databin0 -> 726 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver.java.txt21
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestService.class.databin0 -> 441 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestService.java.txt14
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/ViewTagTest.class.databin0 -> 1645 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/ViewTagTest.java.txt37
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity1.class.databin0 -> 920 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity1.java.txt17
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity2.class.databin0 -> 779 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity2.java.txt24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity3.class.databin0 -> 1067 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity3.java.txt19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity4.class.databin0 -> 1238 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity4.java.txt27
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity5.class.databin0 -> 1067 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity5.java.txt19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity6.class.databin0 -> 2129 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity6.java.txt71
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity7.class.databin0 -> 798 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity7.java.txt17
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity8.class.databin0 -> 1069 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity8.java.txt24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classes.jarbin0 -> 3186 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classpath-jar8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classpath-lib9
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/debuggable.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate-manifest-ignore.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate-manifest.xml22
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate_permissions1.xml21
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate_permissions2.xml18
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate_permissions3.xml18
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity0.xml19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity1.xml32
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity2.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity3.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity4.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportprovider1.xml33
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportprovider2.xml39
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver0.xml19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver1.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver2.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver3.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver4.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver5.xml20
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver6.xml43
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice1.xml25
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice2.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice3.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice4.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice5.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/gen/my/pkg/R.java.txt23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/gen/my/pkg/R2.java.txt5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/grantpermission.xml30
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/ignoremissing.xml6
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/minsdk5targetsdk14.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/minsdk5targetsdk9.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/missingmin.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/missingprefix.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/missingtarget.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/missingusessdk.xml21
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/multiplesdk.xml25
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/LibraryCode.java.txt7
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/MainCode.java.txt7
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/library-manifest.xml31
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/library.properties12
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/main-manifest.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/main-merge.properties13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/main.properties12
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/strings.xml9
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/oldtarget.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/.classpath8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/.project33
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/AndroidManifest.xml38
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/gen/test/pkg/BuildConfig.java.txt6
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/gen/test/pkg/R.java.txt34
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/project.properties11
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable-hdpi/ic_launcher.pngbin0 -> 4147 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable-ldpi/ic_launcher.pngbin0 -> 1723 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable-mdpi/ic_launcher.pngbin0 -> 2574 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable/custombg.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable/custombg2.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/fifth.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/fourth.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/main.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/main_ignore.xml15
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/second.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/sixth.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/third.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/values/strings.xml7
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/values/styles.xml25
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/FourthActivity.java.txt13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/OverdrawActivity.java.txt13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/SecondActivity.java.txt13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/ThirdActivity.java.txt14
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/proguard.cfg36
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/proguard.pro64
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/proguard.properties2
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties114
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties214
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties311
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties414
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/protectedpermissions.xml116
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/protectedpermissions2.xml32
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifest.xml29
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifestInner.xml25
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifestWrong.xml25
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifestWrong2.xml25
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Bar.class.databin0 -> 268 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Bar.java.txt8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo$Bar.class.databin0 -> 319 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo$Baz.class.databin0 -> 388 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo.class.databin0 -> 347 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo.java.txt10
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/appwidget_bg.9.pngbin0 -> 2838 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/appwidget_bg_focus.9.pngbin0 -> 3116 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/filled.pngbin0 -> 4802 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/ic_launcher.pngbin0 -> 4147 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/other.9.pngbin0 -> 2838 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/unrelated.pngbin0 -> 4147 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/frame.pngbin0 -> 9020 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/ic_menu_add_clip_normal.pngbin0 -> 687 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/sample_icon.gifbin0 -> 1797 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/sample_icon.jpgbin0 -> 2141 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/stat_notify_alarm.pngbin0 -> 835 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-nodpi/frame.pngbin0 -> 9020 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-xlarge-nodpi-v11/frame.pngbin0 -> 9020 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/ic_launcher.pngbin0 -> 2574 bytes
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/ic_menu_help.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/states.xml7
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/states2.xml7
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/states3.xml49
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/accessibility.xml9
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/accessibility2.xml12
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/activity_item_two_pane.xml37
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/baseline_weights.xml41
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/baseline_weights2.xml40
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/baseline_weights3.xml39
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/breadcrumbs_in_fragment.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/broken.xml8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar.xml188
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar2.xml52
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar3.xml35
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar4.xml55
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar_suppressed.xml43
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts.xml19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts2.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts3.xml19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts4.xml19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/compound.xml17
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/compound2.xml17
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/compound3.xml18
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/crcrlf.xml14
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/crcrlf_ignore.xml19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/customattrlayout.xml7
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/customview.xml30
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/customview2.xml20
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/default_item_badges.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/deprecation.xml29
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/detailed_item.xml12
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/duplicate.xml8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/edit_textview.xml94
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/edit_type.xml96
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/encoding.xml7
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/encoding2.xml1
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/fragment.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/gridlayout.xml41
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/has_children.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/has_children2.xml11
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/ignores.xml65
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/inefficient_weight.xml44
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/inefficient_weight2.xml22
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/labelfor.xml84
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/labelfor_ignore.xml16
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout1.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout1_ignore.xml26
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout2.xml23
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout3.xml19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout4.xml19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/listseparator.xml3
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace.xml7
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace2.xml29
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace3.xml17
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace4.xml18
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/nested_weights.xml40
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/nested_weights2.xml38
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/note_edit.xml78
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/now_playing_after.xml53
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/onclick.xml79
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/private.xml4
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/scrolling.xml19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/simple.xml7
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/simple_ignore.xml8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/simpleinclude.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/size.xml27
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/size2.xml43
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/sizeincluded.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/textsize.xml51
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/too_deep.xml85
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/too_many.xml413
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/unused_namespace.xml14
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/useless.xml89
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/useless2.xml26
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/useless3.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong0dp.xml103
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_dimension.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace2.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace3.xml24
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace4.xml27
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace5.xml10
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams.xml88
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams2.xml15
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams3.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams4.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams5.xml18
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams6.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams_ignore.xml92
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu-land/actions.xml62
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu-land/actions2.xml62
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu-land/actions2_ignore.xml64
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu/menu.xml16
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu/titles.xml15
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/private_key.pem18
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-cs/arrays.xml9
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-cs/strings.xml11
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-cs/translatedarrays.xml4
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-de-rDE/strings.xml12
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-de/strings.xml4
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-de/typos.xml14
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es-rUS/strings.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/donottranslate.xml4
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/formatstrings.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/formatstrings_ignore.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/strings.xml18
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/strings_ignore.xml20
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/strings_locale.xml20
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-fr/strings.xml8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-it/stringarrays.xml12
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-land/arrays.xml11
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-land/arrays_ignore.xml11
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-land/strings.xml21
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nb/typos.xml22
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nb/typos_locale.xml8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nl-rNL/arrays.xml8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nl-rNL/strings.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/arrays.xml18
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/arrayusage.xml6
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/buttonbar-values.xml15
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/customattr.xml6
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings-version1.xml9
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings-version2.xml6
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings.xml7
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings2.xml6
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings3.xml4
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings4.xml10
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings_ignore.xml7
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/nontranslatable.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/nontranslatable2.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/plurals.xml8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/pxsp.xml34
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/sizestyles.xml17
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/stringarrays.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings.xml31
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings2.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings3.xml10
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings4.xml4
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings_ignore.xml15
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/stylecycle.xml5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/styles.xml15
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/themes.xml8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/themes2.xml10
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/translatedarrays.xml8
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/typography.xml29
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/typos.xml25
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/my/pkg/Test.java.txt10
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/pkg1/Class1.java.txt29
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/pkg2/Class2.java.txt33
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionBarTest.java.txt14
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionTest1.java.txt9
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionTest1_ignore.java.txt10
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionTest2.java.txt9
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/BadImport.java.txt9
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/CustomViewTest.java.txt6
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/Foo.java.txt7
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/Hidden.java.txt14
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ImportFrameActivity.java.txt13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/InflaterTest.java.txt65
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/JavaPerformanceTest.java.txt195
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/NonInternationalizedSmsDetectorTest.java.txt20
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/NotificationTest.java.txt39
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/PasteError.java.txt109
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SdCardTest.java.txt36
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SetJavaScriptEnabled.java.txt28
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest.java.txt66
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest2.java.txt19
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest3.java.txt15
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest4.java.txt15
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest5.java.txt54
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormat2.java.txt14
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormatActivity.java.txt35
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormatActivity2.java.txt20
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormatActivity_ignore.java.txt27
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SuppressTest5.java.txt57
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ToastTest.java.txt41
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/UnusedReference.java.txt12
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/Utf8BomTest.java.data5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WorldWriteableFile.java.txt38
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongAnnotation.java.txt31
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongCastActivity.java.txt16
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongCastActivity2.java.txt15
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongCastActivity3.java.txt11
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongColor.java.txt16
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/unusedR.java.txt14
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/ids.xml6
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/ignorelayout1.xml47
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/layout1.xml45
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/layout2.xml13
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/client/api/DefaultSdkInfoTest.java60
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/client/api/LintClientTest.java30
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/client/api/LintDriverTest.java52
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/detector/api/ClassContextTest.java40
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/detector/api/IssueTest.java222
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/detector/api/LintUtilsTest.java359
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/detector/api/LocationTest.java130
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/detector/api/ScopeTest.java57
537 files changed, 20021 insertions, 0 deletions
diff --git a/lint/cli/Android.mk b/lint/cli/Android.mk
index 5f7da91..dcd1792 100644
--- a/lint/cli/Android.mk
+++ b/lint/cli/Android.mk
@@ -28,3 +28,16 @@ include $(BUILD_HOST_JAVA_LIBRARY)
# Build all sub-directories
include $(call all-makefiles-under,$(LOCAL_PATH))
+
+# Build tests
+include $(CLEAR_VARS)
+
+# Only compile source java files in this lib.
+LOCAL_SRC_FILES := $(call all-java-files-under, src/test/java)
+
+LOCAL_MODULE := lint_checks-tests
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_JAVA_LIBRARIES := common sdklib lint_api lint_checks lint junit easymock asm-tools asm-tree-tools guava-tools layoutlib_api sdktestutils
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/lint/cli/src/test/.classpath b/lint/cli/src/test/.classpath
new file mode 100644
index 0000000..178cd8c
--- /dev/null
+++ b/lint/cli/src/test/.classpath
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="java"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
+ <classpathentry kind="var" path="ANDROID_OUT_FRAMEWORK/easymock.jar"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/lint-api"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/lint-checks"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/lint-cli"/>
+ <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/>
+ <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-tree-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/>
+ <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/guava-tools/guava-13.0.1.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/guava-tools/src.zip"/>
+ <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/lombok-ast/lombok-ast-0.2.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/lombok-ast/src.zip"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/layoutlib_api"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/common"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/testutils"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/lint/cli/src/test/.project b/lint/cli/src/test/.project
new file mode 100644
index 0000000..5713c07
--- /dev/null
+++ b/lint/cli/src/test/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>lint_check-tests</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/lint/cli/src/test/.settings/org.eclipse.core.resources.prefs b/lint/cli/src/test/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..609db57
--- /dev/null
+++ b/lint/cli/src/test/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+encoding//java/com/android/tools/lint/checks/TypoDetectorTest.java=UTF-8
+encoding//java/com/android/tools/lint/checks/TypoLookupTest.java=UTF-8
+encoding//java/com/android/tools/lint/checks/TypographyDetectorTest.java=UTF-8
+encoding//java/com/android/tools/lint/checks/data/res/values-nb/typos.xml=UTF-8
diff --git a/lint/cli/src/test/.settings/org.moreunit.prefs b/lint/cli/src/test/.settings/org.moreunit.prefs
new file mode 100644
index 0000000..4bc8717
--- /dev/null
+++ b/lint/cli/src/test/.settings/org.moreunit.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.moreunit.prefixes=
+org.moreunit.unitsourcefolder=lint_check-tests\:java\:lint-api\:src/main/java\#lint_check-tests\:java\:lint-checks\:src/main/java\#lint_check-tests\:java\:lint-cli\:src/main/java
+org.moreunit.useprojectsettings=true
diff --git a/lint/cli/src/test/java/com/android/tools/lint/LintCliXmlParserTest.java b/lint/cli/src/test/java/com/android/tools/lint/LintCliXmlParserTest.java
new file mode 100644
index 0000000..a6f4aaf
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/LintCliXmlParserTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint;
+
+import com.android.tools.lint.checks.BuiltinIssueRegistry;
+import com.android.tools.lint.client.api.LintClient;
+import com.android.tools.lint.client.api.LintDriver;
+import com.android.tools.lint.detector.api.Context;
+import com.android.tools.lint.detector.api.Issue;
+import com.android.tools.lint.detector.api.Location;
+import com.android.tools.lint.detector.api.Location.Handle;
+import com.android.tools.lint.detector.api.Position;
+import com.android.tools.lint.detector.api.Project;
+import com.android.tools.lint.detector.api.Severity;
+import com.android.tools.lint.detector.api.XmlContext;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.Writer;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class LintCliXmlParserTest extends TestCase {
+ public void test() throws Exception {
+ String xml =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:orientation=\"vertical\" >\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button1\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:text=\"Button\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button2\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:text=\"Button\" />\n" +
+ "\n" +
+ "</LinearLayout>\n";
+ LintCliXmlParser parser = new LintCliXmlParser();
+ File file = File.createTempFile("parsertest", ".xml");
+ Writer fw = new BufferedWriter(new FileWriter(file));
+ fw.write(xml);
+ fw.close();
+ LintClient client = new TestClient();
+ LintDriver driver = new LintDriver(new BuiltinIssueRegistry(), client);
+ Project project = Project.create(client, file.getParentFile(), file.getParentFile());
+ XmlContext context = new XmlContext(driver, project, null, file, null);
+ Document document = parser.parseXml(context);
+ assertNotNull(document);
+
+ // Basic parsing heart beat tests
+ Element linearLayout = (Element) document.getElementsByTagName("LinearLayout").item(0);
+ assertNotNull(linearLayout);
+ NodeList buttons = document.getElementsByTagName("Button");
+ assertEquals(2, buttons.getLength());
+ final String ANDROID_URI = "http://schemas.android.com/apk/res/android";
+ assertEquals("wrap_content",
+ linearLayout.getAttributeNS(ANDROID_URI, "layout_height"));
+
+ // Check attribute positions
+ Attr attr = linearLayout.getAttributeNodeNS(ANDROID_URI, "layout_width");
+ assertNotNull(attr);
+ Location location = parser.getLocation(context, attr);
+ Position start = location.getStart();
+ Position end = location.getEnd();
+ assertEquals(2, start.getLine());
+ assertEquals(xml.indexOf("android:layout_width"), start.getOffset());
+ assertEquals(2, end.getLine());
+ String target = "android:layout_width=\"match_parent\"";
+ assertEquals(xml.indexOf(target) + target.length(), end.getOffset());
+
+ // Check element positions
+ Element button = (Element) buttons.item(0);
+ location = parser.getLocation(context, button);
+ start = location.getStart();
+ end = location.getEnd();
+ assertEquals(6, start.getLine());
+ assertEquals(xml.indexOf("<Button"), start.getOffset());
+ assertEquals(xml.indexOf("/>") + 2, end.getOffset());
+ assertEquals(10, end.getLine());
+ int button1End = end.getOffset();
+
+ Handle handle = parser.createLocationHandle(context, button);
+ Location location2 = handle.resolve();
+ assertSame(location.getFile(), location.getFile());
+ assertNotNull(location2.getStart());
+ assertNotNull(location2.getEnd());
+ assertEquals(6, location2.getStart().getLine());
+ assertEquals(10, location2.getEnd().getLine());
+
+ Element button2 = (Element) buttons.item(1);
+ location = parser.getLocation(context, button2);
+ start = location.getStart();
+ end = location.getEnd();
+ assertEquals(12, start.getLine());
+ assertEquals(xml.indexOf("<Button", button1End), start.getOffset());
+ assertEquals(xml.indexOf("/>", start.getOffset()) + 2, end.getOffset());
+ assertEquals(16, end.getLine());
+
+ parser.dispose(context, document);
+
+ file.delete();
+ }
+
+ public void testLineEndings() throws Exception {
+ // Test for http://code.google.com/p/android/issues/detail?id=22925
+ String xml =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
+ "<LinearLayout>\r\n" +
+ "\r" +
+ "<LinearLayout></LinearLayout>\r\n" +
+ "</LinearLayout>\r\n";
+ LintCliXmlParser parser = new LintCliXmlParser();
+ File file = File.createTempFile("parsertest2", ".xml");
+ Writer fw = new BufferedWriter(new FileWriter(file));
+ fw.write(xml);
+ fw.close();
+ LintClient client = new TestClient();
+ LintDriver driver = new LintDriver(new BuiltinIssueRegistry(), client);
+ Project project = Project.create(client, file.getParentFile(), file.getParentFile());
+ XmlContext context = new XmlContext(driver, project, null, file, null);
+ Document document = parser.parseXml(context);
+ assertNotNull(document);
+
+ file.delete();
+ }
+
+ private static class TestClient extends Main {
+ @Override
+ public void report(Context context, Issue issue, Severity severity, Location location,
+ String message, Object data) {
+ System.out.println(location + ":" + message);
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/MainTest.java b/lint/cli/src/test/java/com/android/tools/lint/MainTest.java
new file mode 100644
index 0000000..ba31ed8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/MainTest.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint;
+
+import com.android.tools.lint.checks.AbstractCheckTest;
+import com.android.tools.lint.checks.AccessibilityDetector;
+import com.android.tools.lint.detector.api.Detector;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.security.Permission;
+import java.util.List;
+
+@SuppressWarnings("javadoc")
+public class MainTest extends AbstractCheckTest {
+ protected String checkLint(String[] args, List<File> files) throws Exception {
+ PrintStream previousOut = System.out;
+ try {
+ final ByteArrayOutputStream output = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(output));
+
+ Main.main(args);
+
+ return output.toString();
+ } finally {
+ System.setOut(previousOut);
+ }
+ }
+
+ private void checkDriver(String expectedOutput, String expectedError, String[] args)
+ throws Exception {
+ PrintStream previousOut = System.out;
+ PrintStream previousErr = System.err;
+ try {
+ // Trap System.exit calls:
+ System.setSecurityManager(new SecurityManager() {
+ @Override
+ public void checkPermission(Permission perm)
+ {
+ // allow anything.
+ }
+ @Override
+ public void checkPermission(Permission perm, Object context)
+ {
+ // allow anything.
+ }
+ @Override
+ public void checkExit(int status) {
+ throw new ExitException();
+ }
+ });
+
+ final ByteArrayOutputStream output = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(output));
+ final ByteArrayOutputStream error = new ByteArrayOutputStream();
+ System.setErr(new PrintStream(error));
+
+ try {
+ Main.main(args);
+ } catch (ExitException e) {
+ // Allow
+ }
+
+ assertEquals(expectedError, cleanup(error.toString()));
+ assertEquals(expectedOutput, cleanup(output.toString()));
+ } finally {
+ // Re-enable system exit for unit test
+ System.setSecurityManager(null);
+
+ System.setOut(previousOut);
+ System.setErr(previousErr);
+ }
+ }
+
+ public void testArguments() throws Exception {
+ checkDriver(
+ // Expected output
+ "\n" +
+ "Scanning MainTest_testArguments: .\n" +
+ "res/layout/accessibility.xml:4: Warning: [Accessibility] Missing contentDescription attribute on image [ContentDescription]\n" +
+ " <ImageView android:id=\"@+id/android_logo\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:src=\"@drawable/android_button\" android:focusable=\"false\" android:clickable=\"false\" android:layout_weight=\"1.0\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/accessibility.xml:5: Warning: [Accessibility] Missing contentDescription attribute on image [ContentDescription]\n" +
+ " <ImageButton android:importantForAccessibility=\"yes\" android:id=\"@+id/android_logo2\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:src=\"@drawable/android_button\" android:focusable=\"false\" android:clickable=\"false\" android:layout_weight=\"1.0\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 2 warnings\n",
+
+ // Expected error
+ "",
+
+ // Args
+ new String[] {
+ "--check",
+ "ContentDescription",
+ "--disable",
+ "LintError",
+ getProjectDir(null, "res/layout/accessibility.xml").getPath()
+
+ });
+ }
+
+ public void testShowDescription() throws Exception {
+ checkDriver(
+ // Expected output
+ "NewApi\n" +
+ "------\n" +
+ "Summary: Finds API accesses to APIs that are not supported in all targeted API\n" +
+ "versions\n" +
+ "\n" +
+ "Priority: 6 / 10\n" +
+ "Severity: Error\n" +
+ "Category: Correctness\n" +
+ "\n" +
+ "This check scans through all the Android API calls in the application and\n" +
+ "warns about any calls that are not available on all versions targeted by this\n" +
+ "application (according to its minimum SDK attribute in the manifest).\n" +
+ "\n" +
+ "If you really want to use this API and don't need to support older devices\n" +
+ "just set the minSdkVersion in your AndroidManifest.xml file.\n" +
+ "If your code is deliberately accessing newer APIs, and you have ensured (e.g.\n" +
+ "with conditional execution) that this code will only ever be called on a\n" +
+ "supported platform, then you can annotate your class or method with the\n" +
+ "@TargetApi annotation specifying the local minimum SDK to apply, such as\n" +
+ "@TargetApi(11), such that this check considers 11 rather than your manifest\n" +
+ "file's minimum SDK as the required API level.\n" +
+ "\n" +
+ "Similarly, you can use tools:targetApi=\"11\" in an XML file to indicate that\n" +
+ "the element will only be inflated in an adequate context.\n" +
+ "\n" +
+ "\n",
+
+ // Expected error
+ "",
+
+ // Args
+ new String[] {
+ "--show",
+ "NewApi"
+ });
+ }
+
+ public void testNonexistentLibrary() throws Exception {
+ checkDriver(
+ "",
+ "Library foo.jar does not exist.\n",
+
+ // Args
+ new String[] {
+ "--libraries",
+ "foo.jar",
+ "prj"
+
+ });
+ }
+
+ public void testMultipleProjects() throws Exception {
+ File project = getProjectDir(null, "bytecode/classes.jar=>libs/classes.jar");
+ checkDriver(
+ "",
+ "The --sources, --classpath and --libraries arguments can only be used with a single project\n",
+
+ // Args
+ new String[] {
+ "--libraries",
+ new File(project, "libs/classes.jar").getPath(),
+ "--disable",
+ "LintError",
+ project.getPath(),
+ project.getPath()
+
+ });
+ }
+
+ public void testClassPath() throws Exception {
+ File project = getProjectDir(null,
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "bytecode/GetterTest.java.txt=>src/test/bytecode/GetterTest.java",
+ "bytecode/GetterTest.jar.data=>bin/classes.jar"
+ );
+ checkDriver(
+ "\n" +
+ "Scanning MainTest_testClassPath: \n" +
+ "src/test/bytecode/GetterTest.java:47: Warning: Calling getter method getFoo1() on self is slower than field access (mFoo1) [FieldGetter]\n" +
+ " getFoo1();\n" +
+ " ~~~~~~~\n" +
+ "src/test/bytecode/GetterTest.java:48: Warning: Calling getter method getFoo2() on self is slower than field access (mFoo2) [FieldGetter]\n" +
+ " getFoo2();\n" +
+ " ~~~~~~~\n" +
+ "src/test/bytecode/GetterTest.java:52: Warning: Calling getter method isBar1() on self is slower than field access (mBar1) [FieldGetter]\n" +
+ " isBar1();\n" +
+ " ~~~~~~\n" +
+ "src/test/bytecode/GetterTest.java:54: Warning: Calling getter method getFoo1() on self is slower than field access (mFoo1) [FieldGetter]\n" +
+ " this.getFoo1();\n" +
+ " ~~~~~~~\n" +
+ "src/test/bytecode/GetterTest.java:55: Warning: Calling getter method getFoo2() on self is slower than field access (mFoo2) [FieldGetter]\n" +
+ " this.getFoo2();\n" +
+ " ~~~~~~~\n" +
+ "0 errors, 5 warnings\n",
+ "",
+
+ // Args
+ new String[] {
+ "--check",
+ "FieldGetter",
+ "--classpath",
+ new File(project, "bin/classes.jar").getPath(),
+ "--disable",
+ "LintError",
+ project.getPath()
+ });
+ }
+
+ public void testLibraries() throws Exception {
+ File project = getProjectDir(null,
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "bytecode/GetterTest.java.txt=>src/test/bytecode/GetterTest.java",
+ "bytecode/GetterTest.jar.data=>bin/classes.jar"
+ );
+ checkDriver(
+ "\n" +
+ "Scanning MainTest_testLibraries: \n" +
+ "\n" +
+ "No issues found.\n",
+ "",
+
+ // Args
+ new String[] {
+ "--check",
+ "FieldGetter",
+ "--libraries",
+ new File(project, "bin/classes.jar").getPath(),
+ "--disable",
+ "LintError",
+ project.getPath()
+ });
+ }
+
+ @Override
+ protected Detector getDetector() {
+ // Sample issue to check by the main driver
+ return new AccessibilityDetector();
+ }
+
+ private static class ExitException extends SecurityException {
+ private static final long serialVersionUID = 1L;
+
+ private ExitException() {
+ super("Unit test");
+ }
+ }
+
+ public void test_getCleanPath() throws Exception {
+ assertEquals("foo", Main.getCleanPath(new File("foo")));
+ String sep = File.separator;
+ assertEquals("foo" + sep + "bar",
+ Main.getCleanPath(new File("foo" + sep + "bar")));
+ assertEquals(sep,
+ Main.getCleanPath(new File(sep)));
+ assertEquals("foo" + sep + "bar",
+ Main.getCleanPath(new File("foo" + sep + "." + sep + "bar")));
+ assertEquals("bar",
+ Main.getCleanPath(new File("foo" + sep + ".." + sep + "bar")));
+ assertEquals("",
+ Main.getCleanPath(new File("foo" + sep + "..")));
+ assertEquals("foo",
+ Main.getCleanPath(new File("foo" + sep + "bar" + sep + "..")));
+ assertEquals("foo" + sep + ".foo" + sep + "bar",
+ Main.getCleanPath(new File("foo" + sep + ".foo" + sep + "bar")));
+ assertEquals("foo" + sep + "bar",
+ Main.getCleanPath(new File("foo" + sep + "bar" + sep + ".")));
+ assertEquals("foo" + sep + "...",
+ Main.getCleanPath(new File("foo" + sep + "...")));
+ assertEquals(".." + sep + "foo",
+ Main.getCleanPath(new File(".." + sep + "foo")));
+ assertEquals(sep + "foo",
+ Main.getCleanPath(new File(sep + "foo")));
+ assertEquals(sep,
+ Main.getCleanPath(new File(sep + "foo" + sep + "..")));
+ assertEquals(sep + "foo",
+ Main.getCleanPath(new File(sep + "foo" + sep + "bar " + sep + "..")));
+ assertEquals(sep + "c:",
+ Main.getCleanPath(new File(sep + "c:")));
+ assertEquals(sep + "c:" + sep + "foo",
+ Main.getCleanPath(new File(sep + "c:" + sep + "foo")));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/XmlReporterTest.java b/lint/cli/src/test/java/com/android/tools/lint/XmlReporterTest.java
new file mode 100644
index 0000000..9ada70f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/XmlReporterTest.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint;
+
+import com.android.tools.lint.checks.AbstractCheckTest;
+import com.android.tools.lint.checks.HardcodedValuesDetector;
+import com.android.tools.lint.checks.ManifestOrderDetector;
+import com.android.tools.lint.detector.api.DefaultPosition;
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Location;
+import com.android.tools.lint.detector.api.Project;
+import com.android.tools.lint.detector.api.Severity;
+import com.android.utils.PositionXmlParser;
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
+
+import org.w3c.dom.Document;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+@SuppressWarnings("javadoc")
+public class XmlReporterTest extends AbstractCheckTest {
+ public void test() throws Exception {
+ File file = new File(getTargetDir(), "report");
+ try {
+ Main client = new Main() {
+ @Override
+ String getRevision() {
+ return "unittest"; // Hardcode version to keep unit test output stable
+ }
+ };
+ file.getParentFile().mkdirs();
+ XmlReporter reporter = new XmlReporter(client, file);
+ Project project = Project.create(client, new File("/foo/bar/Foo"),
+ new File("/foo/bar/Foo"));
+
+ Warning warning1 = new Warning(ManifestOrderDetector.USES_SDK,
+ "<uses-sdk> tag should specify a target API level (the highest verified " +
+ "version; when running on later versions, compatibility behaviors may " +
+ "be enabled) with android:targetSdkVersion=\"?\"",
+ Severity.WARNING, project, null);
+ warning1.line = 6;
+ warning1.file = new File("/foo/bar/Foo/AndroidManifest.xml");
+ warning1.errorLine = " <uses-sdk android:minSdkVersion=\"8\" />\n ^\n";
+ warning1.path = "AndroidManifest.xml";
+ warning1.location = Location.create(warning1.file,
+ new DefaultPosition(6, 4, 198), new DefaultPosition(6, 42, 236));
+
+ Warning warning2 = new Warning(HardcodedValuesDetector.ISSUE,
+ "[I18N] Hardcoded string \"Fooo\", should use @string resource",
+ Severity.WARNING, project, null);
+ warning2.line = 11;
+ warning2.file = new File("/foo/bar/Foo/res/layout/main.xml");
+ warning2.errorLine = " (java.lang.String) android:text=\"Fooo\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n";
+ warning2.path = "res/layout/main.xml";
+ warning2.location = Location.create(warning2.file,
+ new DefaultPosition(11, 8, 377), new DefaultPosition(11, 27, 396));
+
+ List<Warning> warnings = new ArrayList<Warning>();
+ warnings.add(warning1);
+ warnings.add(warning2);
+
+ reporter.write(0, 2, warnings);
+
+ String report = Files.toString(file, Charsets.UTF_8);
+ assertEquals(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<issues format=\"3\" by=\"lint unittest\">\n" +
+ "\n" +
+ " <issue\n" +
+ " id=\"UsesMinSdkAttributes\"\n" +
+ " severity=\"Warning\"\n" +
+ " message=\"&lt;uses-sdk> tag should specify a target API level (the highest verified version; when running on later versions, compatibility behaviors may be enabled) with android:targetSdkVersion=&quot;?&quot;\"\n" +
+ " category=\"Correctness\"\n" +
+ " priority=\"9\"\n" +
+ " summary=\"Checks that the minimum SDK and target SDK attributes are defined\"\n" +
+ " explanation=\"The manifest should contain a `&lt;uses-sdk>` element which defines the minimum API Level required for the application to run, as well as the target version (the highest API level you have tested the version for.)\"\n" +
+ " url=\"http://developer.android.com/guide/topics/manifest/uses-sdk-element.html\"\n" +
+ " errorLine1=\" &lt;uses-sdk android:minSdkVersion=&quot;8&quot; />\"\n" +
+ " errorLine2=\" ^\">\n" +
+ " <location\n" +
+ " file=\"AndroidManifest.xml\"\n" +
+ " line=\"7\"\n" +
+ " column=\"5\"/>\n" +
+ " </issue>\n" +
+ "\n" +
+ " <issue\n" +
+ " id=\"HardcodedText\"\n" +
+ " severity=\"Warning\"\n" +
+ " message=\"[I18N] Hardcoded string &quot;Fooo&quot;, should use @string resource\"\n" +
+ " category=\"Internationalization\"\n" +
+ " priority=\"5\"\n" +
+ " summary=\"Looks for hardcoded text attributes which should be converted to resource lookup\"\n" +
+ " explanation=\"Hardcoding text attributes directly in layout files is bad for several reasons:\n" +
+ "\n" +
+ "* When creating configuration variations (for example for landscape or portrait)you have to repeat the actual text (and keep it up to date when making changes)\n" +
+ "\n" +
+ "* The application cannot be translated to other languages by just adding new translations for existing string resources.\n" +
+ "\n" +
+ "In Eclipse there is a quickfix to automatically extract this hardcoded string into a resource lookup.\"\n" +
+ " errorLine1=\" (java.lang.String) android:text=&quot;Fooo&quot; />\"\n" +
+ " errorLine2=\" ~~~~~~~~~~~~~~~~~~~\">\n" +
+ " <location\n" +
+ " file=\"res/layout/main.xml\"\n" +
+ " line=\"12\"\n" +
+ " column=\"9\"/>\n" +
+ " </issue>\n" +
+ "\n" +
+ "</issues>\n",
+ report);
+
+ // Make sure the XML is valid
+ Document document = new PositionXmlParser().parse(report);
+ assertNotNull(document);
+ assertEquals(2, document.getElementsByTagName("issue").getLength());
+ } finally {
+ file.delete();
+ }
+ }
+
+ public void testFullPaths() throws Exception {
+ File file = new File(getTargetDir(), "report");
+ try {
+ Main client = new Main() {
+ @Override
+ String getRevision() {
+ return "unittest"; // Hardcode version to keep unit test output stable
+ }
+ };
+ client.mFullPath = true;
+
+ file.getParentFile().mkdirs();
+ XmlReporter reporter = new XmlReporter(client, file);
+ Project project = Project.create(client, new File("/foo/bar/Foo"),
+ new File("/foo/bar/Foo"));
+
+ Warning warning1 = new Warning(ManifestOrderDetector.USES_SDK,
+ "<uses-sdk> tag should specify a target API level (the highest verified " +
+ "version; when running on later versions, compatibility behaviors may " +
+ "be enabled) with android:targetSdkVersion=\"?\"",
+ Severity.WARNING, project, null);
+ warning1.line = 6;
+ warning1.file = new File("/foo/bar/../Foo/AndroidManifest.xml");
+ warning1.errorLine = " <uses-sdk android:minSdkVersion=\"8\" />\n ^\n";
+ warning1.path = "AndroidManifest.xml";
+ warning1.location = Location.create(warning1.file,
+ new DefaultPosition(6, 4, 198), new DefaultPosition(6, 42, 236));
+
+ Warning warning2 = new Warning(HardcodedValuesDetector.ISSUE,
+ "[I18N] Hardcoded string \"Fooo\", should use @string resource",
+ Severity.WARNING, project, null);
+ warning2.line = 11;
+ warning2.file = new File("/foo/bar/Foo/res/layout/main.xml");
+ warning2.errorLine = " (java.lang.String) android:text=\"Fooo\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n";
+ warning2.path = "res/layout/main.xml";
+ warning2.location = Location.create(warning2.file,
+ new DefaultPosition(11, 8, 377), new DefaultPosition(11, 27, 396));
+
+ List<Warning> warnings = new ArrayList<Warning>();
+ warnings.add(warning1);
+ warnings.add(warning2);
+
+ reporter.write(0, 2, warnings);
+
+ String report = Files.toString(file, Charsets.UTF_8);
+ assertEquals(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<issues format=\"3\" by=\"lint unittest\">\n" +
+ "\n" +
+ " <issue\n" +
+ " id=\"UsesMinSdkAttributes\"\n" +
+ " severity=\"Warning\"\n" +
+ " message=\"&lt;uses-sdk> tag should specify a target API level (the highest verified version; when running on later versions, compatibility behaviors may be enabled) with android:targetSdkVersion=&quot;?&quot;\"\n" +
+ " category=\"Correctness\"\n" +
+ " priority=\"9\"\n" +
+ " summary=\"Checks that the minimum SDK and target SDK attributes are defined\"\n" +
+ " explanation=\"The manifest should contain a `&lt;uses-sdk>` element which defines the minimum API Level required for the application to run, as well as the target version (the highest API level you have tested the version for.)\"\n" +
+ " url=\"http://developer.android.com/guide/topics/manifest/uses-sdk-element.html\"\n" +
+ " errorLine1=\" &lt;uses-sdk android:minSdkVersion=&quot;8&quot; />\"\n" +
+ " errorLine2=\" ^\">\n" +
+ " <location\n" +
+ " file=\"/foo/Foo/AndroidManifest.xml\"\n" +
+ " line=\"7\"\n" +
+ " column=\"5\"/>\n" +
+ " </issue>\n" +
+ "\n" +
+ " <issue\n" +
+ " id=\"HardcodedText\"\n" +
+ " severity=\"Warning\"\n" +
+ " message=\"[I18N] Hardcoded string &quot;Fooo&quot;, should use @string resource\"\n" +
+ " category=\"Internationalization\"\n" +
+ " priority=\"5\"\n" +
+ " summary=\"Looks for hardcoded text attributes which should be converted to resource lookup\"\n" +
+ " explanation=\"Hardcoding text attributes directly in layout files is bad for several reasons:\n" +
+ "\n" +
+ "* When creating configuration variations (for example for landscape or portrait)you have to repeat the actual text (and keep it up to date when making changes)\n" +
+ "\n" +
+ "* The application cannot be translated to other languages by just adding new translations for existing string resources.\n" +
+ "\n" +
+ "In Eclipse there is a quickfix to automatically extract this hardcoded string into a resource lookup.\"\n" +
+ " errorLine1=\" (java.lang.String) android:text=&quot;Fooo&quot; />\"\n" +
+ " errorLine2=\" ~~~~~~~~~~~~~~~~~~~\">\n" +
+ " <location\n" +
+ " file=\"/foo/bar/Foo/res/layout/main.xml\"\n" +
+ " line=\"12\"\n" +
+ " column=\"9\"/>\n" +
+ " </issue>\n" +
+ "\n" +
+ "</issues>\n",
+ report);
+
+ // Make sure the XML is valid
+ Document document = new PositionXmlParser().parse(report);
+ assertNotNull(document);
+ assertEquals(2, document.getElementsByTagName("issue").getLength());
+ } finally {
+ file.delete();
+ }
+ }
+
+ @Override
+ protected Detector getDetector() {
+ fail("Not used in this test");
+ return null;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/AbstractCheckTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/AbstractCheckTest.java
new file mode 100644
index 0000000..d54962a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/AbstractCheckTest.java
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.testutils.SdkTestCase;
+import com.android.tools.lint.LintCliXmlParser;
+import com.android.tools.lint.LombokParser;
+import com.android.tools.lint.Main;
+import com.android.tools.lint.Reporter;
+import com.android.tools.lint.TextReporter;
+import com.android.tools.lint.client.api.Configuration;
+import com.android.tools.lint.client.api.DefaultConfiguration;
+import com.android.tools.lint.client.api.IDomParser;
+import com.android.tools.lint.client.api.IJavaParser;
+import com.android.tools.lint.client.api.IssueRegistry;
+import com.android.tools.lint.client.api.LintClient;
+import com.android.tools.lint.client.api.LintDriver;
+import com.android.tools.lint.detector.api.Context;
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Issue;
+import com.android.tools.lint.detector.api.Location;
+import com.android.tools.lint.detector.api.Project;
+import com.android.tools.lint.detector.api.Scope;
+import com.android.tools.lint.detector.api.Severity;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.CodeSource;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+
+/** Common utility methods for the various lint check tests */
+@SuppressWarnings("javadoc")
+public abstract class AbstractCheckTest extends SdkTestCase {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ BuiltinIssueRegistry.reset();
+ }
+
+ protected abstract Detector getDetector();
+
+ private Detector mDetector;
+
+ private Detector getDetectorInstance() {
+ if (mDetector == null) {
+ mDetector = getDetector();
+ }
+
+ return mDetector;
+ }
+
+ protected List<Issue> getIssues() {
+ List<Issue> issues = new ArrayList<Issue>();
+ Class<? extends Detector> detectorClass = getDetectorInstance().getClass();
+ // Get the list of issues from the registry and filter out others, to make sure
+ // issues are properly registered
+ List<Issue> candidates = new BuiltinIssueRegistry().getIssues();
+ for (Issue issue : candidates) {
+ if (issue.getDetectorClass() == detectorClass) {
+ issues.add(issue);
+ }
+ }
+
+ return issues;
+ }
+
+ private class CustomIssueRegistry extends IssueRegistry {
+ @Override
+ public List<Issue> getIssues() {
+ return AbstractCheckTest.this.getIssues();
+ }
+ }
+
+ protected String lintFiles(String... relativePaths) throws Exception {
+ List<File> files = new ArrayList<File>();
+ File targetDir = getTargetDir();
+ for (String relativePath : relativePaths) {
+ File file = getTestfile(targetDir, relativePath);
+ assertNotNull(file);
+ files.add(file);
+ }
+
+ addManifestFile(targetDir);
+
+ return checkLint(files);
+ }
+
+ protected String checkLint(List<File> files) throws Exception {
+ mOutput = new StringBuilder();
+ TestLintClient lintClient = createClient();
+ String result = lintClient.analyze(files);
+
+ // The output typically contains a few directory/filenames.
+ // On Windows we need to change the separators to the unix-style
+ // forward slash to make the test as OS-agnostic as possible.
+ if (File.separatorChar != '/') {
+ result = result.replace(File.separatorChar, '/');
+ }
+
+ for (File f : files) {
+ deleteFile(f);
+ }
+
+ return result;
+ }
+
+ protected TestLintClient createClient() {
+ return new TestLintClient();
+ }
+
+ protected TestConfiguration getConfiguration(LintClient client, Project project) {
+ return new TestConfiguration(client, project, null);
+ }
+
+ protected void configureDriver(LintDriver driver) {
+ }
+
+ /**
+ * Run lint on the given files when constructed as a separate project
+ * @return The output of the lint check. On Windows, this transforms all directory
+ * separators to the unix-style forward slash.
+ */
+ protected String lintProject(String... relativePaths) throws Exception {
+ File projectDir = getProjectDir(null, relativePaths);
+ return checkLint(Collections.singletonList(projectDir));
+ }
+
+ @Override
+ protected File getTargetDir() {
+ File targetDir = new File(getTempDir(), getClass().getSimpleName() + "_" + getName());
+ addCleanupDir(targetDir);
+ return targetDir;
+ }
+
+ /** Creates a project directory structure from the given files */
+ protected File getProjectDir(String name, String ...relativePaths) throws Exception {
+ assertFalse("getTargetDir must be overridden to make a unique directory",
+ getTargetDir().equals(getTempDir()));
+
+ File projectDir = getTargetDir();
+ if (name != null) {
+ projectDir = new File(projectDir, name);
+ }
+ if (!projectDir.exists()) {
+ assertTrue(projectDir.getPath(), projectDir.mkdirs());
+ }
+
+ List<File> files = new ArrayList<File>();
+ for (String relativePath : relativePaths) {
+ File file = getTestfile(projectDir, relativePath);
+ assertNotNull(file);
+ files.add(file);
+ }
+
+ addManifestFile(projectDir);
+ return projectDir;
+ }
+
+ private void addManifestFile(File projectDir) throws IOException {
+ // Ensure that there is at least a manifest file there to make it a valid project
+ // as far as Lint is concerned:
+ if (!new File(projectDir, "AndroidManifest.xml").exists()) {
+ File manifest = new File(projectDir, "AndroidManifest.xml");
+ FileWriter fw = new FileWriter(manifest);
+ fw.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " package=\"foo.bar2\"\n" +
+ " android:versionCode=\"1\"\n" +
+ " android:versionName=\"1.0\" >\n" +
+ "</manifest>\n");
+ fw.close();
+ }
+ }
+
+ private StringBuilder mOutput = null;
+
+ @Override
+ protected InputStream getTestResource(String relativePath, boolean expectExists) {
+ String path = "data" + File.separator + relativePath; //$NON-NLS-1$
+ InputStream stream =
+ AbstractCheckTest.class.getResourceAsStream(path);
+ if (!expectExists && stream == null) {
+ return null;
+ }
+ return stream;
+ }
+
+ protected boolean isEnabled(Issue issue) {
+ Class<? extends Detector> detectorClass = getDetectorInstance().getClass();
+ if (issue.getDetectorClass() == detectorClass) {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected boolean includeParentPath() {
+ return false;
+ }
+
+ protected EnumSet<Scope> getLintScope(List<File> file) {
+ return null;
+ }
+
+ public String getSuperClass(Project project, String name) {
+ return null;
+ }
+
+ public class TestLintClient extends Main {
+ private StringWriter mWriter = new StringWriter();
+
+ TestLintClient() {
+ mReporters.add(new TextReporter(this, mWriter, false));
+ }
+
+ @Override
+ public String getSuperClass(Project project, String name) {
+ String superClass = AbstractCheckTest.this.getSuperClass(project, name);
+ if (superClass != null) {
+ return superClass;
+ }
+
+ return super.getSuperClass(project, name);
+ }
+
+ public String analyze(List<File> files) throws Exception {
+ mDriver = new LintDriver(new CustomIssueRegistry(), this);
+ configureDriver(mDriver);
+ mDriver.analyze(files, getLintScope(files));
+
+ Collections.sort(mWarnings);
+
+ for (Reporter reporter : mReporters) {
+ reporter.write(mErrorCount, mWarningCount, mWarnings);
+ }
+
+ mOutput.append(mWriter.toString());
+
+ if (mOutput.length() == 0) {
+ mOutput.append("No warnings.");
+ }
+
+ String result = mOutput.toString();
+ if (result.equals("\nNo issues found.\n")) {
+ result = "No warnings.";
+ }
+
+ result = cleanup(result);
+
+ return result;
+ }
+
+ public String getErrors() throws Exception {
+ return mWriter.toString();
+ }
+
+ @Override
+ public void report(Context context, Issue issue, Severity severity, Location location,
+ String message, Object data) {
+ if (issue == IssueRegistry.LINT_ERROR) {
+ return;
+ }
+
+ if (severity == Severity.FATAL) {
+ // Treat fatal errors like errors in the golden files.
+ severity = Severity.ERROR;
+ }
+
+ // For messages into all secondary locations to ensure they get
+ // specifically included in the text report
+ if (location != null && location.getSecondary() != null) {
+ Location l = location.getSecondary();
+ while (l != null) {
+ if (l.getMessage() == null) {
+ l.setMessage("<No location-specific message");
+ }
+ l = l.getSecondary();
+ }
+ }
+
+ super.report(context, issue, severity, location, message, data);
+ }
+
+ @Override
+ public void log(Throwable exception, String format, Object... args) {
+ if (exception != null) {
+ exception.printStackTrace();
+ }
+ StringBuilder sb = new StringBuilder();
+ if (format != null) {
+ sb.append(String.format(format, args));
+ }
+ if (exception != null) {
+ sb.append(exception.toString());
+ }
+ System.err.println(sb);
+
+ if (exception != null) {
+ fail(exception.toString());
+ }
+ }
+
+ @Override
+ public IDomParser getDomParser() {
+ return new LintCliXmlParser();
+ }
+
+ @Override
+ public IJavaParser getJavaParser() {
+ return new LombokParser();
+ }
+
+ @Override
+ public Configuration getConfiguration(Project project) {
+ return AbstractCheckTest.this.getConfiguration(this, project);
+ }
+
+ @Override
+ public File findResource(String relativePath) {
+ if (relativePath.equals("platform-tools/api/api-versions.xml")) {
+ File rootDir = getRootDir();
+ if (rootDir != null) {
+ File file = new File(rootDir, "development" + File.separator + "sdk"
+ + File.separator + "api-versions.xml");
+ return file;
+ }
+ } else if (relativePath.startsWith("tools/support/")) {
+ String base = relativePath.substring("tools/support/".length());
+ File rootDir = getRootDir();
+ if (rootDir != null) {
+ File file = new File(rootDir, "sdk" + File.separator + "files"
+ + File.separator + "typos"
+ + File.separator + base);
+ return file;
+ }
+ } else {
+ fail("Unit tests don't support arbitrary resource lookup yet.");
+ }
+
+ return super.findResource(relativePath);
+ }
+ }
+
+ /**
+ * Returns the Android source tree root dir.
+ * @return the root dir or null if it couldn't be computed.
+ */
+ private File getRootDir() {
+ CodeSource source = getClass().getProtectionDomain().getCodeSource();
+ if (source != null) {
+ URL location = source.getLocation();
+ try {
+ File dir = new File(location.toURI());
+ assertTrue(dir.getPath(), dir.exists());
+ File rootDir = dir.getParentFile().getParentFile().getParentFile()
+ .getParentFile().getParentFile().getParentFile();
+
+ // check if "settings.gradle" is there. This will let us know if we need
+ // to go up one extra level, which is the case when running the tests
+ // from gradle.
+ File settingsGradle = new File(rootDir, "settings.gradle"); //$NON-NLS-1$
+ if (settingsGradle.isFile()) {
+ rootDir = rootDir.getParentFile();
+ }
+
+ return rootDir;
+ } catch (URISyntaxException e) {
+ fail(e.getLocalizedMessage());
+ }
+ }
+
+ return null;
+ }
+
+ public class TestConfiguration extends DefaultConfiguration {
+ protected TestConfiguration(
+ @NonNull LintClient client,
+ @NonNull Project project,
+ @Nullable Configuration parent) {
+ super(client, project, parent);
+ }
+
+ public TestConfiguration(
+ @NonNull LintClient client,
+ @Nullable Project project,
+ @Nullable Configuration parent,
+ @NonNull File configFile) {
+ super(client, project, parent, configFile);
+ }
+
+ @Override
+ @NonNull
+ protected Severity getDefaultSeverity(@NonNull Issue issue) {
+ // In unit tests, include issues that are ignored by default
+ Severity severity = super.getDefaultSeverity(issue);
+ if (severity == Severity.IGNORE) {
+ return Severity.WARNING;
+ }
+ return severity;
+ }
+
+ @Override
+ public boolean isEnabled(Issue issue) {
+ return AbstractCheckTest.this.isEnabled(issue);
+ }
+
+ @Override
+ public void ignore(Context context, Issue issue, Location location, String message,
+ Object data) {
+ fail("Not supported in tests.");
+ }
+
+ @Override
+ public void setSeverity(Issue issue, Severity severity) {
+ fail("Not supported in tests.");
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/AccessibilityDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/AccessibilityDetectorTest.java
new file mode 100644
index 0000000..fe24446
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/AccessibilityDetectorTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class AccessibilityDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new AccessibilityDetector();
+ }
+
+ public void testAccessibility() throws Exception {
+ assertEquals(
+ "res/layout/accessibility.xml:4: Warning: [Accessibility] Missing contentDescription attribute on image [ContentDescription]\n" +
+ " <ImageView android:id=\"@+id/android_logo\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:src=\"@drawable/android_button\" android:focusable=\"false\" android:clickable=\"false\" android:layout_weight=\"1.0\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/accessibility.xml:5: Warning: [Accessibility] Missing contentDescription attribute on image [ContentDescription]\n" +
+ " <ImageButton android:importantForAccessibility=\"yes\" android:id=\"@+id/android_logo2\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:src=\"@drawable/android_button\" android:focusable=\"false\" android:clickable=\"false\" android:layout_weight=\"1.0\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/accessibility.xml:9: Warning: Do not set both contentDescription and hint: the contentDescription will mask the hint [ContentDescription]\n" +
+ " <EditText android:hint=\"@string/label\" android:id=\"@+android:id/summary\" android:contentDescription=\"@string/label\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 3 warnings\n",
+
+ lintProject("res/layout/accessibility2.xml=>res/layout/accessibility.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/AlwaysShowActionDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/AlwaysShowActionDetectorTest.java
new file mode 100644
index 0000000..f7879bb
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/AlwaysShowActionDetectorTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class AlwaysShowActionDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new AlwaysShowActionDetector();
+ }
+
+ public void testXmlMenus() throws Exception {
+ assertEquals(
+ "res/menu-land/actions.xml:6: Warning: Prefer \"ifRoom\" instead of \"always\" [AlwaysShowAction]\n" +
+ " android:showAsAction=\"always|collapseActionView\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/menu-land/actions.xml:13: <No location-specific message\n" +
+ " res/menu-land/actions.xml:18: <No location-specific message\n" +
+ " res/menu-land/actions.xml:54: <No location-specific message\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject("res/menu-land/actions.xml"));
+ }
+
+ public void testXmlMenusWithFlags() throws Exception {
+ assertEquals(
+ "res/menu-land/actions2.xml:6: Warning: Prefer \"ifRoom\" instead of \"always\" [AlwaysShowAction]\n" +
+ " android:showAsAction=\"always|collapseActionView\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/menu-land/actions2.xml:13: <No location-specific message\n" +
+ " res/menu-land/actions2.xml:18: <No location-specific message\n" +
+ " res/menu-land/actions2.xml:54: <No location-specific message\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject("res/menu-land/actions2.xml"));
+ }
+
+ public void testJavaFail() throws Exception {
+ assertEquals(
+ "src/test/pkg/ActionTest1.java:7: Warning: Prefer \"SHOW_AS_ACTION_IF_ROOM\" instead of \"SHOW_AS_ACTION_ALWAYS\" [AlwaysShowAction]\n" +
+ " System.out.println(MenuItem.SHOW_AS_ACTION_ALWAYS);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ // Only references to ALWAYS
+ lintProject("src/test/pkg/ActionTest1.java.txt=>src/test/pkg/ActionTest1.java"));
+ }
+ public void testJavaPass() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ // Both references to ALWAYS and IF_ROOM
+ lintProject(
+ "src/test/pkg/ActionTest1.java.txt=>src/test/pkg/ActionTest1.java",
+ "src/test/pkg/ActionTest2.java.txt=>src/test/pkg/ActionTest2.java"));
+ }
+
+ public void testSuppress() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/menu-land/actions2_ignore.xml",
+ "src/test/pkg/ActionTest1_ignore.java.txt=>src/test/pkg/ActionTest1.java"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/AnnotationDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/AnnotationDetectorTest.java
new file mode 100644
index 0000000..becca80
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/AnnotationDetectorTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Issue;
+
+import java.util.List;
+
+@SuppressWarnings("javadoc")
+public class AnnotationDetectorTest extends AbstractCheckTest {
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/WrongAnnotation.java:9: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
+ " public static void foobar(View view, @SuppressLint(\"NewApi\") int foo) { // Invalid: class-file check\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/WrongAnnotation.java:10: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
+ " @SuppressLint(\"NewApi\") // Invalid\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/WrongAnnotation.java:12: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
+ " @SuppressLint({\"SdCardPath\", \"NewApi\"}) // Invalid: class-file based check on local variable\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/WrongAnnotation.java:14: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
+ " @android.annotation.SuppressLint({\"SdCardPath\", \"NewApi\"}) // Invalid (FQN)\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/WrongAnnotation.java:28: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
+ " @SuppressLint(\"NewApi\")\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "5 errors, 0 warnings\n",
+
+ lintProject(
+ "src/test/pkg/WrongAnnotation.java.txt=>src/test/pkg/WrongAnnotation.java"
+ ));
+ }
+
+ @Override
+ protected Detector getDetector() {
+ return new AnnotationDetector();
+ }
+
+ @Override
+ protected List<Issue> getIssues() {
+ List<Issue> issues = super.getIssues();
+
+ // Need these issues on to be found by the registry as well to look up scope
+ // in id references (these ids are referenced in the unit test java file below)
+ issues.add(ApiDetector.UNSUPPORTED);
+ issues.add(SdCardDetector.ISSUE);
+
+ return issues;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java
new file mode 100644
index 0000000..e42280f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java
@@ -0,0 +1,719 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Project;
+
+@SuppressWarnings("javadoc")
+public class ApiDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ApiDetector();
+ }
+
+ public void testXmlApi1() throws Exception {
+ assertEquals(
+ "res/color/colors.xml:9: Error: @android:color/holo_red_light requires API level 14 (current min is 1) [NewApi]\n" +
+ " <item name=\"android:windowBackground\"> @android:color/holo_red_light </item>\n" +
+ " ^\n" +
+ "res/layout/layout.xml:9: Error: View requires API level 5 (current min is 1): <QuickContactBadge> [NewApi]\n" +
+ " <QuickContactBadge\n" +
+ " ^\n" +
+ "res/layout/layout.xml:15: Error: View requires API level 11 (current min is 1): <CalendarView> [NewApi]\n" +
+ " <CalendarView\n" +
+ " ^\n" +
+ "res/layout/layout.xml:21: Error: View requires API level 14 (current min is 1): <GridLayout> [NewApi]\n" +
+ " <GridLayout\n" +
+ " ^\n" +
+ "res/layout/layout.xml:22: Error: @android:attr/actionBarSplitStyle requires API level 14 (current min is 1) [NewApi]\n" +
+ " foo=\"@android:attr/actionBarSplitStyle\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/layout.xml:23: Error: @android:color/holo_red_light requires API level 14 (current min is 1) [NewApi]\n" +
+ " bar=\"@android:color/holo_red_light\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/values/themes.xml:9: Error: @android:color/holo_red_light requires API level 14 (current min is 1) [NewApi]\n" +
+ " <item name=\"android:windowBackground\"> @android:color/holo_red_light </item>\n" +
+ " ^\n" +
+ "7 errors, 0 warnings\n" +
+ "",
+
+ lintProject(
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "apicheck/layout.xml=>res/layout/layout.xml",
+ "apicheck/themes.xml=>res/values/themes.xml",
+ "apicheck/themes.xml=>res/color/colors.xml"
+ ));
+ }
+
+ public void testXmlApi14() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "apicheck/layout.xml=>res/layout/layout.xml",
+ "apicheck/themes.xml=>res/values/themes.xml",
+ "apicheck/themes.xml=>res/color/colors.xml"
+ ));
+ }
+
+ public void testXmlApi1TargetApi() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "apicheck/layout_targetapi.xml=>res/layout/layout.xml"
+ ));
+ }
+
+ public void testXmlApiFolderVersion11() throws Exception {
+ assertEquals(
+ "res/color-v11/colors.xml:9: Error: @android:color/holo_red_light requires API level 14 (current min is 1) [NewApi]\n" +
+ " <item name=\"android:windowBackground\"> @android:color/holo_red_light </item>\n" +
+ " ^\n" +
+ "res/layout-v11/layout.xml:21: Error: View requires API level 14 (current min is 1): <GridLayout> [NewApi]\n" +
+ " <GridLayout\n" +
+ " ^\n" +
+ "res/layout-v11/layout.xml:22: Error: @android:attr/actionBarSplitStyle requires API level 14 (current min is 1) [NewApi]\n" +
+ " foo=\"@android:attr/actionBarSplitStyle\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout-v11/layout.xml:23: Error: @android:color/holo_red_light requires API level 14 (current min is 1) [NewApi]\n" +
+ " bar=\"@android:color/holo_red_light\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/values-v11/themes.xml:9: Error: @android:color/holo_red_light requires API level 14 (current min is 1) [NewApi]\n" +
+ " <item name=\"android:windowBackground\"> @android:color/holo_red_light </item>\n" +
+ " ^\n" +
+ "5 errors, 0 warnings\n" +
+ "",
+
+ lintProject(
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "apicheck/layout.xml=>res/layout-v11/layout.xml",
+ "apicheck/themes.xml=>res/values-v11/themes.xml",
+ "apicheck/themes.xml=>res/color-v11/colors.xml"
+ ));
+ }
+
+ public void testXmlApiFolderVersion14() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "apicheck/layout.xml=>res/layout-v14/layout.xml",
+ "apicheck/themes.xml=>res/values-v14/themes.xml",
+ "apicheck/themes.xml=>res/color-v14/colors.xml"
+ ));
+ }
+
+ public void testApi1() throws Exception {
+ assertEquals(
+ "src/foo/bar/ApiCallTest.java:20: Error: Call requires API level 11 (current min is 1): android.app.Activity#getActionBar [NewApi]\n" +
+ " getActionBar(); // API 11\n" +
+ " ~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:24: Error: Class requires API level 8 (current min is 1): org.w3c.dom.DOMErrorHandler [NewApi]\n" +
+ " Class<?> clz = DOMErrorHandler.class; // API 8\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:27: Error: Call requires API level 3 (current min is 1): android.widget.Chronometer#getOnChronometerTickListener [NewApi]\n" +
+ " chronometer.getOnChronometerTickListener(); // API 3 \n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:30: Error: Call requires API level 11 (current min is 1): android.widget.Chronometer#setTextIsSelectable [NewApi]\n" +
+ " chronometer.setTextIsSelectable(true); // API 11\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:33: Error: Field requires API level 11 (current min is 1): dalvik.bytecode.OpcodeInfo#MAXIMUM_VALUE [NewApi]\n" +
+ " int field = OpcodeInfo.MAXIMUM_VALUE; // API 11\n" +
+ " ~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:38: Error: Field requires API level 14 (current min is 1): android.app.ApplicationErrorReport#batteryInfo [NewApi]\n" +
+ " BatteryInfo batteryInfo = getReport().batteryInfo;\n" +
+ " ~~~~~~~~~~~\n" +
+ // Note: the above error range is wrong; should be pointing to the second
+ "src/foo/bar/ApiCallTest.java:41: Error: Field requires API level 11 (current min is 1): android.graphics.PorterDuff.Mode#OVERLAY [NewApi]\n" +
+ " Mode mode = PorterDuff.Mode.OVERLAY; // API 11\n" +
+ " ~~~~~~~\n" +
+ "7 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest.java.txt=>src/foo/bar/ApiCallTest.java",
+ "apicheck/ApiCallTest.class.data=>bin/classes/foo/bar/ApiCallTest.class"
+ ));
+ }
+
+ public void testApi2() throws Exception {
+ assertEquals(
+ "src/foo/bar/ApiCallTest.java:20: Error: Call requires API level 11 (current min is 2): android.app.Activity#getActionBar [NewApi]\n" +
+ " getActionBar(); // API 11\n" +
+ " ~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:24: Error: Class requires API level 8 (current min is 2): org.w3c.dom.DOMErrorHandler [NewApi]\n" +
+ " Class<?> clz = DOMErrorHandler.class; // API 8\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:27: Error: Call requires API level 3 (current min is 2): android.widget.Chronometer#getOnChronometerTickListener [NewApi]\n" +
+ " chronometer.getOnChronometerTickListener(); // API 3 \n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:30: Error: Call requires API level 11 (current min is 2): android.widget.Chronometer#setTextIsSelectable [NewApi]\n" +
+ " chronometer.setTextIsSelectable(true); // API 11\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:33: Error: Field requires API level 11 (current min is 2): dalvik.bytecode.OpcodeInfo#MAXIMUM_VALUE [NewApi]\n" +
+ " int field = OpcodeInfo.MAXIMUM_VALUE; // API 11\n" +
+ " ~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:38: Error: Field requires API level 14 (current min is 2): android.app.ApplicationErrorReport#batteryInfo [NewApi]\n" +
+ " BatteryInfo batteryInfo = getReport().batteryInfo;\n" +
+ " ~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:41: Error: Field requires API level 11 (current min is 2): android.graphics.PorterDuff.Mode#OVERLAY [NewApi]\n" +
+ " Mode mode = PorterDuff.Mode.OVERLAY; // API 11\n" +
+ " ~~~~~~~\n" +
+ "7 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk2.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest.java.txt=>src/foo/bar/ApiCallTest.java",
+ "apicheck/ApiCallTest.class.data=>bin/classes/foo/bar/ApiCallTest.class"
+ ));
+ }
+
+ public void testApi4() throws Exception {
+ assertEquals(
+ "src/foo/bar/ApiCallTest.java:20: Error: Call requires API level 11 (current min is 4): android.app.Activity#getActionBar [NewApi]\n" +
+ " getActionBar(); // API 11\n" +
+ " ~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:24: Error: Class requires API level 8 (current min is 4): org.w3c.dom.DOMErrorHandler [NewApi]\n" +
+ " Class<?> clz = DOMErrorHandler.class; // API 8\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:30: Error: Call requires API level 11 (current min is 4): android.widget.Chronometer#setTextIsSelectable [NewApi]\n" +
+ " chronometer.setTextIsSelectable(true); // API 11\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:33: Error: Field requires API level 11 (current min is 4): dalvik.bytecode.OpcodeInfo#MAXIMUM_VALUE [NewApi]\n" +
+ " int field = OpcodeInfo.MAXIMUM_VALUE; // API 11\n" +
+ " ~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:38: Error: Field requires API level 14 (current min is 4): android.app.ApplicationErrorReport#batteryInfo [NewApi]\n" +
+ " BatteryInfo batteryInfo = getReport().batteryInfo;\n" +
+ " ~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:41: Error: Field requires API level 11 (current min is 4): android.graphics.PorterDuff.Mode#OVERLAY [NewApi]\n" +
+ " Mode mode = PorterDuff.Mode.OVERLAY; // API 11\n" +
+ " ~~~~~~~\n" +
+ "6 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest.java.txt=>src/foo/bar/ApiCallTest.java",
+ "apicheck/ApiCallTest.class.data=>bin/classes/foo/bar/ApiCallTest.class"
+ ));
+ }
+
+ public void testApi10() throws Exception {
+ assertEquals(
+ "src/foo/bar/ApiCallTest.java:20: Error: Call requires API level 11 (current min is 10): android.app.Activity#getActionBar [NewApi]\n" +
+ " getActionBar(); // API 11\n" +
+ " ~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:30: Error: Call requires API level 11 (current min is 10): android.widget.Chronometer#setTextIsSelectable [NewApi]\n" +
+ " chronometer.setTextIsSelectable(true); // API 11\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:33: Error: Field requires API level 11 (current min is 10): dalvik.bytecode.OpcodeInfo#MAXIMUM_VALUE [NewApi]\n" +
+ " int field = OpcodeInfo.MAXIMUM_VALUE; // API 11\n" +
+ " ~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:38: Error: Field requires API level 14 (current min is 10): android.app.ApplicationErrorReport#batteryInfo [NewApi]\n" +
+ " BatteryInfo batteryInfo = getReport().batteryInfo;\n" +
+ " ~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest.java:41: Error: Field requires API level 11 (current min is 10): android.graphics.PorterDuff.Mode#OVERLAY [NewApi]\n" +
+ " Mode mode = PorterDuff.Mode.OVERLAY; // API 11\n" +
+ " ~~~~~~~\n" +
+ "5 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk10.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest.java.txt=>src/foo/bar/ApiCallTest.java",
+ "apicheck/ApiCallTest.class.data=>bin/classes/foo/bar/ApiCallTest.class"
+ ));
+ }
+
+ public void testApi14() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest.java.txt=>src/foo/bar/ApiCallTest.java",
+ "apicheck/ApiCallTest.class.data=>bin/classes/foo/bar/ApiCallTest.class"
+ ));
+ }
+
+ public void testInheritStatic() throws Exception {
+ assertEquals(
+ "src/foo/bar/ApiCallTest5.java:16: Error: Call requires API level 11 (current min is 2): android.view.View#resolveSizeAndState [NewApi]\n" +
+ " int measuredWidth = View.resolveSizeAndState(widthMeasureSpec,\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest5.java:18: Error: Call requires API level 11 (current min is 2): android.view.View#resolveSizeAndState [NewApi]\n" +
+ " int measuredHeight = resolveSizeAndState(heightMeasureSpec,\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest5.java:20: Error: Call requires API level 11 (current min is 2): android.view.View#combineMeasuredStates [NewApi]\n" +
+ " View.combineMeasuredStates(0, 0);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiCallTest5.java:21: Error: Call requires API level 11 (current min is 2): android.view.View#combineMeasuredStates [NewApi]\n" +
+ " ApiCallTest5.combineMeasuredStates(0, 0);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~\n" +
+ "4 errors, 0 warnings\n" +
+ "",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk2.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest5.java.txt=>src/foo/bar/ApiCallTest5.java",
+ "apicheck/ApiCallTest5.class.data=>bin/classes/foo/bar/ApiCallTest5.class"
+ ));
+ }
+
+ public void testInheritLocal() throws Exception {
+ // Test virtual dispatch in a local class which extends some other local class (which
+ // in turn extends an Android API)
+ assertEquals(
+ "src/test/pkg/ApiCallTest3.java:10: Error: Call requires API level 11 (current min is 1): android.app.Activity#getActionBar [NewApi]\n" +
+ " getActionBar(); // API 11\n" +
+ " ~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n" +
+ "",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "apicheck/Intermediate.java.txt=>src/test/pkg/Intermediate.java",
+ "apicheck/ApiCallTest3.java.txt=>src/test/pkg/ApiCallTest3.java",
+ "apicheck/ApiCallTest3.class.data=>bin/classes/test/pkg/ApiCallTest3.class",
+ "apicheck/Intermediate.class.data=>bin/classes/test/pkg/Intermediate.class"
+ ));
+ }
+
+ public void testViewClassLayoutReference() throws Exception {
+ assertEquals(
+ "res/layout/view.xml:9: Error: View requires API level 5 (current min is 1): <QuickContactBadge> [NewApi]\n" +
+ " <view\n" +
+ " ^\n" +
+ "res/layout/view.xml:16: Error: View requires API level 11 (current min is 1): <CalendarView> [NewApi]\n" +
+ " <view\n" +
+ " ^\n" +
+ "res/layout/view.xml:24: Error: ?android:attr/dividerHorizontal requires API level 11 (current min is 1) [NewApi]\n" +
+ " unknown=\"?android:attr/dividerHorizontal\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/view.xml:25: Error: ?android:attr/textColorLinkInverse requires API level 11 (current min is 1) [NewApi]\n" +
+ " android:textColor=\"?android:attr/textColorLinkInverse\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "4 errors, 0 warnings\n" +
+ "",
+
+ lintProject(
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "apicheck/view.xml=>res/layout/view.xml"
+ ));
+ }
+
+ public void testIOException() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=35190
+ assertEquals(
+ "src/test/pkg/ApiCallTest6.java:8: Error: Call requires API level 9 (current min is 1): new java.io.IOException [NewApi]\n" +
+ " IOException ioException = new IOException(throwable);\n" +
+ " ~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "apicheck/Intermediate.java.txt=>src/test/pkg/Intermediate.java",
+ "apicheck/ApiCallTest6.java.txt=>src/test/pkg/ApiCallTest6.java",
+ "apicheck/ApiCallTest6.class.data=>bin/classes/test/pkg/ApiCallTest6.class"
+ ));
+ }
+
+
+ // Test suppressing errors -- on classes, methods etc.
+
+ public void testSuppress() throws Exception {
+ assertEquals(
+ // These errors are correctly -not- suppressed because they
+ // appear in method3 (line 74-98) which is annotated with a
+ // @SuppressLint annotation specifying only an unrelated issue id
+
+ "src/foo/bar/SuppressTest1.java:76: Error: Call requires API level 11 (current min is 1): android.app.Activity#getActionBar [NewApi]\n" +
+ " getActionBar(); // API 11\n" +
+ " ~~~~~~~~~~~~\n" +
+ "src/foo/bar/SuppressTest1.java:80: Error: Class requires API level 8 (current min is 1): org.w3c.dom.DOMErrorHandler [NewApi]\n" +
+ " Class<?> clz = DOMErrorHandler.class; // API 8\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/SuppressTest1.java:83: Error: Call requires API level 3 (current min is 1): android.widget.Chronometer#getOnChronometerTickListener [NewApi]\n" +
+ " chronometer.getOnChronometerTickListener(); // API 3\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/SuppressTest1.java:86: Error: Call requires API level 11 (current min is 1): android.widget.Chronometer#setTextIsSelectable [NewApi]\n" +
+ " chronometer.setTextIsSelectable(true); // API 11\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/SuppressTest1.java:89: Error: Field requires API level 11 (current min is 1): dalvik.bytecode.OpcodeInfo#MAXIMUM_VALUE [NewApi]\n" +
+ " int field = OpcodeInfo.MAXIMUM_VALUE; // API 11\n" +
+ " ~~~~~~~~~~~~~\n" +
+ "src/foo/bar/SuppressTest1.java:94: Error: Field requires API level 14 (current min is 1): android.app.ApplicationErrorReport#batteryInfo [NewApi]\n" +
+ " BatteryInfo batteryInfo = getReport().batteryInfo;\n" +
+ " ~~~~~~~~~~~\n" +
+ "src/foo/bar/SuppressTest1.java:97: Error: Field requires API level 11 (current min is 1): android.graphics.PorterDuff.Mode#OVERLAY [NewApi]\n" +
+ " Mode mode = PorterDuff.Mode.OVERLAY; // API 11\n" +
+ " ~~~~~~~\n" +
+
+ // Note: These annotations are within the methods, not ON the methods, so they have
+ // no effect (because they don't end up in the bytecode)
+
+
+ "src/foo/bar/SuppressTest4.java:19: Error: Field requires API level 14 (current min is 1): android.app.ApplicationErrorReport#batteryInfo [NewApi]\n" +
+ " BatteryInfo batteryInfo = report.batteryInfo;\n" +
+ " ~~~~~~~~~~~\n" +
+ "8 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "apicheck/SuppressTest1.java.txt=>src/foo/bar/SuppressTest1.java",
+ "apicheck/SuppressTest1.class.data=>bin/classes/foo/bar/SuppressTest1.class",
+ "apicheck/SuppressTest2.java.txt=>src/foo/bar/SuppressTest2.java",
+ "apicheck/SuppressTest2.class.data=>bin/classes/foo/bar/SuppressTest2.class",
+ "apicheck/SuppressTest3.java.txt=>src/foo/bar/SuppressTest3.java",
+ "apicheck/SuppressTest3.class.data=>bin/classes/foo/bar/SuppressTest3.class",
+ "apicheck/SuppressTest4.java.txt=>src/foo/bar/SuppressTest4.java",
+ "apicheck/SuppressTest4.class.data=>bin/classes/foo/bar/SuppressTest4.class"
+ ));
+ }
+
+ public void testSuppressInnerClasses() throws Exception {
+ assertEquals(
+ // These errors are correctly -not- suppressed because they
+ // appear outside the middle inner class suppressing its own errors
+ // and its child's errors
+ "src/test/pkg/ApiCallTest4.java:9: Error: Call requires API level 14 (current min is 1): new android.widget.GridLayout [NewApi]\n" +
+ " new GridLayout(null, null, 0);\n" +
+ " ~~~~~~~~~~\n" +
+ "src/test/pkg/ApiCallTest4.java:38: Error: Call requires API level 14 (current min is 1): new android.widget.GridLayout [NewApi]\n" +
+ " new GridLayout(null, null, 0);\n" +
+ " ~~~~~~~~~~\n" +
+ "2 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest4.java.txt=>src/test/pkg/ApiCallTest4.java",
+ "apicheck/ApiCallTest4.class.data=>bin/classes/test/pkg/ApiCallTest4.class",
+ "apicheck/ApiCallTest4$1.class.data=>bin/classes/test/pkg/ApiCallTest4$1.class",
+ "apicheck/ApiCallTest4$InnerClass1.class.data=>bin/classes/test/pkg/ApiCallTest4$InnerClass1.class",
+ "apicheck/ApiCallTest4$InnerClass2.class.data=>bin/classes/test/pkg/ApiCallTest4$InnerClass2.class",
+ "apicheck/ApiCallTest4$InnerClass1$InnerInnerClass1.class.data=>bin/classes/test/pkg/ApiCallTest4$InnerClass1$InnerInnerClass1.class"
+ ));
+ }
+
+ public void testApiTargetAnnotation() throws Exception {
+ assertEquals(
+ "src/foo/bar/ApiTargetTest.java:13: Error: Class requires API level 8 (current min is 1): org.w3c.dom.DOMErrorHandler [NewApi]\n" +
+ " Class<?> clz = DOMErrorHandler.class; // API 8\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiTargetTest.java:25: Error: Class requires API level 8 (current min is 4): org.w3c.dom.DOMErrorHandler [NewApi]\n" +
+ " Class<?> clz = DOMErrorHandler.class; // API 8\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "src/foo/bar/ApiTargetTest.java:39: Error: Class requires API level 8 (current min is 7): org.w3c.dom.DOMErrorHandler [NewApi]\n" +
+ " Class<?> clz = DOMErrorHandler.class; // API 8\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "3 errors, 0 warnings\n" +
+ "",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "apicheck/ApiTargetTest.java.txt=>src/foo/bar/ApiTargetTest.java",
+ "apicheck/ApiTargetTest.class.data=>bin/classes/foo/bar/ApiTargetTest.class",
+ "apicheck/ApiTargetTest$LocalClass.class.data=>bin/classes/foo/bar/ApiTargetTest$LocalClass.class"
+ ));
+ }
+
+ public void testTargetAnnotationInner() throws Exception {
+ assertEquals(
+ "src/test/pkg/ApiTargetTest2.java:32: Error: Call requires API level 14 (current min is 3): new android.widget.GridLayout [NewApi]\n" +
+ " new GridLayout(null, null, 0);\n" +
+ " ~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "apicheck/ApiTargetTest2.java.txt=>src/test/pkg/ApiTargetTest2.java",
+ "apicheck/ApiTargetTest2.class.data=>bin/classes/test/pkg/ApiTargetTest2.class",
+ "apicheck/ApiTargetTest2$1.class.data=>bin/classes/test/pkg/ApiTargetTest2$1.class",
+ "apicheck/ApiTargetTest2$1$2.class.data=>bin/classes/test/pkg/ApiTargetTest2$1$2.class",
+ "apicheck/ApiTargetTest2$1$1.class.data=>bin/classes/test/pkg/ApiTargetTest2$1$1.class"
+ ));
+ }
+
+ public void testSuper() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=36384
+ assertEquals(
+ "src/test/pkg/ApiCallTest7.java:8: Error: Call requires API level 9 (current min is 4): new java.io.IOException [NewApi]\n" +
+ " super(message, cause); // API 9\n" +
+ " ~~~~~\n" +
+ "src/test/pkg/ApiCallTest7.java:12: Error: Call requires API level 9 (current min is 4): new java.io.IOException [NewApi]\n" +
+ " super.toString(); throw new IOException((Throwable) null); // API 9\n" +
+ " ~~~~~~~~~~~\n" +
+ "2 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest7.java.txt=>src/test/pkg/ApiCallTest7.java",
+ "apicheck/ApiCallTest7.class.data=>bin/classes/test/pkg/ApiCallTest7.class"
+ ));
+ }
+
+ public void testEnums() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=36951
+ assertEquals(
+ "src/test/pkg/TestEnum.java:26: Error: Enum value requires API level 11 (current min is 4): android.graphics.PorterDuff.Mode#OVERLAY [NewApi]\n" +
+ " case OVERLAY: {\n" +
+ " ~~~~~~~\n" +
+ "src/test/pkg/TestEnum.java:37: Error: Enum value requires API level 11 (current min is 4): android.graphics.PorterDuff.Mode#OVERLAY [NewApi]\n" +
+ " case OVERLAY: {\n" +
+ " ~~~~~~~\n" +
+ "src/test/pkg/TestEnum.java:61: Error: Enum for switch requires API level 11 (current min is 4): android.renderscript.Element.DataType [NewApi]\n" +
+ " switch (type) {\n" +
+ " ^\n" +
+ "3 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "apicheck/TestEnum.java.txt=>src/test/pkg/TestEnum.java",
+ "apicheck/TestEnum.class.data=>bin/classes/test/pkg/TestEnum.class"
+ ));
+ }
+
+ @Override
+ public String getSuperClass(Project project, String name) {
+ // For testInterfaceInheritance
+ if (name.equals("android/database/sqlite/SQLiteStatement")) {
+ return "android/database/sqlite/SQLiteProgram";
+ } else if (name.equals("android/database/sqlite/SQLiteProgram")) {
+ return "android/database/sqlite/SQLiteClosable";
+ } else if (name.equals("android/database/sqlite/SQLiteClosable")) {
+ return "java/lang/Object";
+ }
+ return null;
+ }
+
+ public void testInterfaceInheritance() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=38004
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "apicheck/CloseTest.java.txt=>src/test/pkg/CloseTest.java",
+ "apicheck/CloseTest.class.data=>bin/classes/test/pkg/CloseTest.class"
+ ));
+ }
+
+ public void testInnerClassPositions() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=38113
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest8.java.txt=>src/test/pkg/ApiCallTest8.java",
+ "apicheck/ApiCallTest8.class.data=>bin/classes/test/pkg/ApiCallTest8.class"
+ ));
+ }
+
+ public void testManifestReferences() throws Exception {
+ assertEquals(
+ "AndroidManifest.xml:15: Error: @android:style/Theme.Holo requires API level 11 (current min is 4) [NewApi]\n" +
+ " android:theme=\"@android:style/Theme.Holo\" >\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/holomanifest.xml=>AndroidManifest.xml"
+ ));
+ }
+
+ public void testSuppressFieldAnnotations() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=38626
+ assertEquals(
+ "src/test/pkg/ApiCallTest9.java:9: Error: Call requires API level 14 (current min is 4): new android.widget.GridLayout [NewApi]\n" +
+ " private GridLayout field1 = new GridLayout(null);\n" +
+ " ~~~~~~~~~~\n" +
+ "src/test/pkg/ApiCallTest9.java:12: Error: Call requires API level 14 (current min is 4): new android.widget.GridLayout [NewApi]\n" +
+ " private static GridLayout field2 = new GridLayout(null);\n" +
+ " ~~~~~~~~~~\n" +
+ "2 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest9.java.txt=>src/test/pkg/ApiCallTest9.java",
+ "apicheck/ApiCallTest9.class.data=>bin/classes/test/pkg/ApiCallTest9.class"
+ ));
+ }
+
+ public void test38195() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=38195
+ assertEquals(
+ "bin/classes/TestLint.class: Error: Call requires API level 16 (current min is 4): new android.database.SQLException [NewApi]\n" +
+ "bin/classes/TestLint.class: Error: Call requires API level 9 (current min is 4): java.lang.String#isEmpty [NewApi]\n" +
+ "bin/classes/TestLint.class: Error: Call requires API level 9 (current min is 4): new java.sql.SQLException [NewApi]\n" +
+ "3 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ /*
+ Compiled from "TestLint.java"
+ public class test.pkg.TestLint extends java.lang.Object{
+ public test.pkg.TestLint();
+ Code:
+ 0: aload_0
+ 1: invokespecial #8; //Method java/lang/Object."<init>":()V
+ 4: return
+
+ public void test(java.lang.Exception) throws java.lang.Exception;
+ Code:
+ 0: ldc #19; //String
+ 2: invokevirtual #21; //Method java/lang/String.isEmpty:()Z
+ 5: istore_2
+ 6: new #27; //class java/sql/SQLException
+ 9: dup
+ 10: ldc #29; //String error on upgrade:
+ 12: aload_1
+ 13: invokespecial #31; //Method java/sql/SQLException."<init>":
+ (Ljava/lang/String;Ljava/lang/Throwable;)V
+ 16: athrow
+
+ public void test2(java.lang.Exception) throws java.lang.Exception;
+ Code:
+ 0: new #39; //class android/database/SQLException
+ 3: dup
+ 4: ldc #29; //String error on upgrade:
+ 6: aload_1
+ 7: invokespecial #41; //Method android/database/SQLException.
+ "<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V
+ 10: athrow
+ }
+ */
+ "apicheck/TestLint.class.data=>bin/classes/TestLint.class"
+ ));
+ }
+
+ public void testAllowLocalMethodsImplementingInaccessible() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=39030
+ assertEquals(
+ "src/test/pkg/ApiCallTest10.java:25: Error: Call requires API level 14 (current min is 4): android.view.View#onPopulateAccessibilityEvent [NewApi]\n" +
+ " super.onPopulateAccessibilityEvent(event); // Valid lint warning\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/ApiCallTest10.java:31: Error: Call requires API level 14 (current min is 4): android.view.View#dispatchGenericFocusedEvent [NewApi]\n" +
+ " return super.dispatchGenericFocusedEvent(event); // Should flag this\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/ApiCallTest10.java:40: Error: Call requires API level 14 (current min is 4): android.view.View#dispatchHoverEvent [NewApi]\n" +
+ " dispatchHoverEvent(null);\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "3 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest10.java.txt=>src/test/pkg/ApiCallTest10.java",
+ "apicheck/ApiCallTest10.class.data=>bin/classes/test/pkg/ApiCallTest10.class"
+ ));
+ }
+
+ public void testOverrideUnknownTarget() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest11.java.txt=>src/test/pkg/ApiCallTest11.java",
+ "apicheck/ApiCallTest11.class.data=>bin/classes/test/pkg/ApiCallTest11.class"
+ ));
+ }
+
+ public void testOverride() throws Exception {
+ assertEquals(
+ "src/test/pkg/ApiCallTest11.java:13: Error: This method is not overriding anything with the current build target, but will in API level 11 (current target is 3): test.pkg.ApiCallTest11#getActionBar [Override]\n" +
+ " public ActionBar getActionBar() {\n" +
+ " ~~~~~~~~~~~~\n" +
+ "src/test/pkg/ApiCallTest11.java:17: Error: This method is not overriding anything with the current build target, but will in API level 17 (current target is 3): test.pkg.ApiCallTest11#isDestroyed [Override]\n" +
+ " public boolean isDestroyed() {\n" +
+ " ~~~~~~~~~~~\n" +
+ "src/test/pkg/ApiCallTest11.java:39: Error: This method is not overriding anything with the current build target, but will in API level 11 (current target is 3): test.pkg.ApiCallTest11.MyLinear#setDividerDrawable [Override]\n" +
+ " public void setDividerDrawable(Drawable dividerDrawable) {\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "3 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "project.properties1=>project.properties",
+ "apicheck/ApiCallTest11.java.txt=>src/test/pkg/ApiCallTest11.java",
+ "apicheck/ApiCallTest11.class.data=>bin/classes/test/pkg/ApiCallTest11.class",
+ "apicheck/ApiCallTest11$MyLinear.class.data=>bin/classes/test/pkg/ApiCallTest11$MyLinear.class",
+ "apicheck/ApiCallTest11$MyActivity.class.data=>bin/classes/test/pkg/ApiCallTest11$MyActivity.class"
+ ));
+ }
+
+ public void testDateFormat() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=40876
+ assertEquals(
+ "src/test/pkg/ApiCallTest12.java:18: Error: Call requires API level 9 (current min is 4): java.text.DateFormatSymbols#getInstance [NewApi]\n" +
+ " new SimpleDateFormat(\"yyyy-MM-dd\", DateFormatSymbols.getInstance());\n" +
+ " ~~~~~~~~~~~\n" +
+ "src/test/pkg/ApiCallTest12.java:23: Error: The pattern character 'L' requires API level 9 (current min is 4) : \"yyyy-MM-dd LL\" [NewApi]\n" +
+ " new SimpleDateFormat(\"yyyy-MM-dd LL\", Locale.US);\n" +
+ " ^\n" +
+ "src/test/pkg/ApiCallTest12.java:25: Error: The pattern character 'c' requires API level 9 (current min is 4) : \"cc yyyy-MM-dd\" [NewApi]\n" +
+ " SimpleDateFormat format = new SimpleDateFormat(\"cc yyyy-MM-dd\");\n" +
+ " ^\n" +
+ "3 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "project.properties1=>project.properties",
+ "apicheck/ApiCallTest12.java.txt=>src/test/pkg/ApiCallTest12.java",
+ "apicheck/ApiCallTest12.class.data=>bin/classes/test/pkg/ApiCallTest12.class"
+ ));
+ }
+
+ public void testDateFormatOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk10.xml=>AndroidManifest.xml",
+ "project.properties1=>project.properties",
+ "apicheck/ApiCallTest12.java.txt=>src/test/pkg/ApiCallTest12.java",
+ "apicheck/ApiCallTest12.class.data=>bin/classes/test/pkg/ApiCallTest12.class"
+ ));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ApiLookupTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ApiLookupTest.java
new file mode 100644
index 0000000..252ec5e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ApiLookupTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Severity;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.RandomAccessFile;
+import java.io.StringWriter;
+
+@SuppressWarnings("javadoc")
+public class ApiLookupTest extends AbstractCheckTest {
+ private final ApiLookup mDb = ApiLookup.get(new TestLintClient());
+
+ public void test1() {
+ assertEquals(5, mDb.getFieldVersion("android/Manifest$permission", "AUTHENTICATE_ACCOUNTS"));
+ assertTrue(mDb.getFieldVersion("android/R$attr", "absListViewStyle") <= 1);
+ assertEquals(11, mDb.getFieldVersion("android/R$attr", "actionMenuTextAppearance"));
+ assertEquals(5, mDb.getCallVersion("android/graphics/drawable/BitmapDrawable",
+ "<init>", "(Landroid/content/res/Resources;Ljava/lang/String;)V"));
+ assertEquals(4, mDb.getCallVersion("android/graphics/drawable/BitmapDrawable",
+ "setTargetDensity", "(Landroid/util/DisplayMetrics;)V"));
+ assertEquals(7, mDb.getClassVersion("android/app/WallpaperInfo"));
+ assertEquals(11, mDb.getClassVersion("android/widget/StackView"));
+ assertTrue(mDb.getClassVersion("ava/text/ChoiceFormat") <= 1);
+
+ // Class lookup: Unknown class
+ assertEquals(-1, mDb.getClassVersion("foo/Bar"));
+ // Field lookup: Unknown class
+ assertEquals(-1, mDb.getFieldVersion("foo/Bar", "FOOBAR"));
+ // Field lookup: Unknown field
+ assertEquals(-1, mDb.getFieldVersion("android/Manifest$permission", "FOOBAR"));
+ // Method lookup: Unknown class
+ assertEquals(-1, mDb.getCallVersion("foo/Bar",
+ "<init>", "(Landroid/content/res/Resources;Ljava/lang/String;)V"));
+ // Method lookup: Unknown name
+ assertEquals(-1, mDb.getCallVersion("android/graphics/drawable/BitmapDrawable",
+ "foo", "(Landroid/content/res/Resources;Ljava/lang/String;)V"));
+ // Method lookup: Unknown argument list
+ assertEquals(-1, mDb.getCallVersion("android/graphics/drawable/BitmapDrawable",
+ "<init>", "(I)V"));
+ }
+
+ public void test2() {
+ // Regression test:
+ // This used to return 11 because of some wildcard syntax in the signature
+ assertTrue(mDb.getCallVersion("java/lang/Object", "getClass", "()") <= 1);
+ }
+
+ public void testIssue26467() {
+ assertTrue(mDb.getCallVersion("java/nio/ByteBuffer", "array", "()") <= 1);
+ assertEquals(9, mDb.getCallVersion("java/nio/Buffer", "array", "()"));
+ }
+
+ public void testNoInheritedConstructors() {
+ assertTrue(mDb.getCallVersion("java/util/zip/ZipOutputStream", "<init>", "()") <= 1);
+ assertTrue(mDb.getCallVersion("android/app/AliasActivity", "<init>", "(Landroid/content/Context;I)") <= 1);
+ }
+
+ public void testIssue35190() {
+ assertEquals(9, mDb.getCallVersion("java/io/IOException", "<init>",
+ "(Ljava/lang/Throwable;)V"));
+ }
+
+ public void testInheritInterfaces() {
+ // The onPreferenceStartFragment is inherited via the
+ // android/preference/PreferenceFragment$OnPreferenceStartFragmentCallback
+ // interface
+ assertEquals(11, mDb.getCallVersion("android/preference/PreferenceActivity",
+ "onPreferenceStartFragment",
+ "(Landroid/preference/PreferenceFragment;Landroid/preference/Preference;)"));
+ }
+
+ public void testIsValidPackage() {
+ assertTrue(mDb.isValidJavaPackage("java/lang/Integer"));
+ assertTrue(mDb.isValidJavaPackage("javax/crypto/Cipher"));
+ assertTrue(mDb.isValidJavaPackage("java/awt/font/NumericShaper"));
+
+ assertFalse(mDb.isValidJavaPackage("javax/swing/JButton"));
+ assertFalse(mDb.isValidJavaPackage("java/rmi/Naming"));
+ assertFalse(mDb.isValidJavaPackage("java/lang/instrument/Instrumentation"));
+ }
+
+ @Override
+ protected Detector getDetector() {
+ fail("This is not used in the ApiDatabase test");
+ return null;
+ }
+
+ private File mCacheDir;
+ private StringBuilder mLogBuffer = new StringBuilder();
+
+ public void testCorruptedCacheHandling() throws Exception {
+ ApiLookup lookup;
+
+ // Real cache:
+ mCacheDir = new TestLintClient().getCacheDir(true);
+ mLogBuffer.setLength(0);
+ lookup = ApiLookup.get(new LookupTestClient());
+ assertEquals(11, lookup.getFieldVersion("android/R$attr", "actionMenuTextAppearance"));
+ assertNotNull(lookup);
+ assertEquals("", mLogBuffer.toString()); // No warnings
+ ApiLookup.dispose();
+
+ // Custom cache dir: should also work
+ mCacheDir = new File(getTempDir(), "test-cache");
+ mCacheDir.mkdirs();
+ mLogBuffer.setLength(0);
+ lookup = ApiLookup.get(new LookupTestClient());
+ assertEquals(11, lookup.getFieldVersion("android/R$attr", "actionMenuTextAppearance"));
+ assertNotNull(lookup);
+ assertEquals("", mLogBuffer.toString()); // No warnings
+ ApiLookup.dispose();
+
+ // Now truncate cache file
+ File cacheFile = new File(mCacheDir,
+ ApiLookup.getCacheFileName("api-versions.xml")); //$NON-NLS-1$
+ mLogBuffer.setLength(0);
+ assertTrue(cacheFile.exists());
+ RandomAccessFile raf = new RandomAccessFile(cacheFile, "rw");
+ // Truncate file in half
+ raf.setLength(100); // Broken header
+ raf.close();
+ lookup = ApiLookup.get(new LookupTestClient());
+ String message = mLogBuffer.toString();
+ // NOTE: This test is incompatible with the DEBUG_FORCE_REGENERATE_BINARY and WRITE_STATS
+ // flags in the ApiLookup class, so if the test fails during development and those are
+ // set, clear them.
+ assertTrue(message.contains("Please delete the file and restart the IDE/lint:"));
+ assertTrue(message.contains(mCacheDir.getPath()));
+ ApiLookup.dispose();
+
+ mLogBuffer.setLength(0);
+ assertTrue(cacheFile.exists());
+ raf = new RandomAccessFile(cacheFile, "rw");
+ // Truncate file in half in the data portion
+ raf.setLength(raf.length() / 2);
+ raf.close();
+ lookup = ApiLookup.get(new LookupTestClient());
+ // This data is now truncated: lookup returns the wrong size.
+ try {
+ assertNotNull(lookup);
+ lookup.getFieldVersion("android/R$attr", "actionMenuTextAppearance");
+ fail("Can't look up bogus data");
+ } catch (Throwable t) {
+ // Expected this: the database is corrupted.
+ }
+ assertTrue(message.contains("Please delete the file and restart the IDE/lint:"));
+ assertTrue(message.contains(mCacheDir.getPath()));
+ ApiLookup.dispose();
+
+ mLogBuffer.setLength(0);
+ assertTrue(cacheFile.exists());
+ raf = new RandomAccessFile(cacheFile, "rw");
+ // Truncate file to 0 bytes
+ raf.setLength(0);
+ raf.close();
+ lookup = ApiLookup.get(new LookupTestClient());
+ assertEquals(11, lookup.getFieldVersion("android/R$attr", "actionMenuTextAppearance"));
+ assertNotNull(lookup);
+ assertEquals("", mLogBuffer.toString()); // No warnings
+ ApiLookup.dispose();
+ }
+
+ private final class LookupTestClient extends TestLintClient {
+ @Override
+ public File getCacheDir(boolean create) {
+ assertNotNull(mCacheDir);
+ if (create && !mCacheDir.exists()) {
+ mCacheDir.mkdirs();
+ }
+ return mCacheDir;
+ }
+
+ @Override
+ public void log(Severity severity, Throwable exception, String format,
+ Object... args) {
+ if (format != null) {
+ mLogBuffer.append(String.format(format, args));
+ mLogBuffer.append('\n');
+ }
+ if (exception != null) {
+ StringWriter writer = new StringWriter();
+ exception.printStackTrace(new PrintWriter(writer));
+ mLogBuffer.append(writer.toString());
+ mLogBuffer.append('\n');
+ }
+ }
+
+ @Override
+ public void log(Throwable exception, String format, Object... args) {
+ log(Severity.WARNING, exception, format, args);
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ArraySizeDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ArraySizeDetectorTest.java
new file mode 100644
index 0000000..127e7f8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ArraySizeDetectorTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class ArraySizeDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ArraySizeDetector();
+ }
+ public void testArraySizes() throws Exception {
+ assertEquals(
+ "res/values/arrays.xml:3: Warning: Array security_questions has an inconsistent number of items (3 in values-nl-rNL/arrays.xml, 4 in values-cs/arrays.xml) [InconsistentArrays]\n" +
+ " <string-array name=\"security_questions\">\n" +
+ " ^\n" +
+ " res/values-cs/arrays.xml:3: Declaration with array size (4)\n" +
+ " res/values-es/strings.xml:12: Declaration with array size (4)\n" +
+ " res/values-nl-rNL/arrays.xml:3: Declaration with array size (3)\n" +
+ "res/values/arrays.xml:10: Warning: Array signal_strength has an inconsistent number of items (5 in values/arrays.xml, 6 in values-land/arrays.xml) [InconsistentArrays]\n" +
+ " <array name=\"signal_strength\">\n" +
+ " ^\n" +
+ " res/values-land/arrays.xml:2: Declaration with array size (6)\n" +
+ "0 errors, 2 warnings\n" +
+ "",
+
+ lintProject(
+ "res/values/arrays.xml",
+ "res/values-cs/arrays.xml",
+ "res/values-land/arrays.xml",
+ "res/values-nl-rNL/arrays.xml",
+ "res/values-es/strings.xml"));
+ }
+
+ public void testMultipleArrays() throws Exception {
+ assertEquals(
+ "res/values/stringarrays.xml:3: Warning: Array map_density_desc has an inconsistent number of items (5 in values/stringarrays.xml, 1 in values-it/stringarrays.xml) [InconsistentArrays]\n" +
+ " <string-array name=\"map_density_desc\">\n" +
+ " ^\n" +
+ " res/values-it/stringarrays.xml:6: Declaration with array size (1)\n" +
+ "0 errors, 1 warnings\n",
+
+ lintProject(
+ "res/values-it/stringarrays.xml",
+ "res/values/stringarrays.xml"));
+ }
+
+ public void testArraySizesSuppressed() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/values/arrays.xml",
+ "res/values-land/arrays_ignore.xml=>res/values-land/arrays.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ButtonDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ButtonDetectorTest.java
new file mode 100644
index 0000000..989f33c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ButtonDetectorTest.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Issue;
+
+@SuppressWarnings("javadoc")
+public class ButtonDetectorTest extends AbstractCheckTest {
+ private static Issue sTestIssue;
+
+ @Override
+ protected boolean isEnabled(Issue issue) {
+ return super.isEnabled(issue) && sTestIssue == null || issue == sTestIssue;
+
+ }
+
+ @Override
+ protected Detector getDetector() {
+ return new ButtonDetector();
+ }
+
+ public void testButtonOrder() throws Exception {
+ sTestIssue = ButtonDetector.ORDER;
+ assertEquals(
+ "res/layout/buttonbar.xml:12: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:44: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:92: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:124: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:140: Warning: OK button should be on the right (was \"Ok | CANCEL\", should be \"CANCEL | Ok\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:156: Warning: OK button should be on the right (was \"OK | Abort\", should be \"Abort | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:177: Warning: Cancel button should be on the left (was \"Send | Cancel\", should be \"Cancel | Send\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "0 errors, 7 warnings\n" +
+ "",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/layout/buttonbar.xml",
+ "res/values/buttonbar-values.xml"));
+ }
+
+ public void testButtonOrder2() throws Exception {
+ // If the layout is in v14, it had better have the right order
+ sTestIssue = ButtonDetector.ORDER;
+ assertEquals(
+ "res/layout-v14/buttonbar.xml:12: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-v14/buttonbar.xml:44: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-v14/buttonbar.xml:92: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-v14/buttonbar.xml:124: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-v14/buttonbar.xml:140: Warning: OK button should be on the right (was \"Ok | CANCEL\", should be \"CANCEL | Ok\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-v14/buttonbar.xml:156: Warning: OK button should be on the right (was \"OK | Abort\", should be \"Abort | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-v14/buttonbar.xml:177: Warning: Cancel button should be on the left (was \"Send | Cancel\", should be \"Cancel | Send\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "0 errors, 7 warnings\n" +
+ "",
+
+ lintProject(
+ "minsdk5targetsdk14.xml=>AndroidManifest.xml",
+ "res/layout/buttonbar.xml=>res/layout-v14/buttonbar.xml",
+ "res/values/buttonbar-values.xml"));
+ }
+
+ public void testButtonOrder3() throws Exception {
+ // Similar to test 3, but also complain if the -v version is *higher* than 14
+ sTestIssue = ButtonDetector.ORDER;
+ assertEquals(
+ "res/layout-v16/buttonbar.xml:12: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-v16/buttonbar.xml:44: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-v16/buttonbar.xml:92: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-v16/buttonbar.xml:124: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-v16/buttonbar.xml:140: Warning: OK button should be on the right (was \"Ok | CANCEL\", should be \"CANCEL | Ok\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-v16/buttonbar.xml:156: Warning: OK button should be on the right (was \"OK | Abort\", should be \"Abort | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-v16/buttonbar.xml:177: Warning: Cancel button should be on the left (was \"Send | Cancel\", should be \"Cancel | Send\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "0 errors, 7 warnings\n" +
+ "",
+
+ lintProject(
+ "minsdk5targetsdk14.xml=>AndroidManifest.xml",
+ "res/layout/buttonbar.xml=>res/layout-v16/buttonbar.xml",
+ "res/values/buttonbar-values.xml"));
+ }
+
+ public void testButtonOrder4() throws Exception {
+ // Targeting 14 but using a layout that also needs to work for older platforms:
+ sTestIssue = ButtonDetector.ORDER;
+ assertEquals(
+ "res/layout/buttonbar.xml:12: Warning: Layout uses the wrong button order for API >= 14: Create a layout-v14/buttonbar.xml file with opposite order: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:44: Warning: Layout uses the wrong button order for API >= 14: Create a layout-v14/buttonbar.xml file with opposite order: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:92: Warning: Layout uses the wrong button order for API >= 14: Create a layout-v14/buttonbar.xml file with opposite order: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:124: Warning: Layout uses the wrong button order for API >= 14: Create a layout-v14/buttonbar.xml file with opposite order: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:140: Warning: Layout uses the wrong button order for API >= 14: Create a layout-v14/buttonbar.xml file with opposite order: OK button should be on the right (was \"Ok | CANCEL\", should be \"CANCEL | Ok\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:156: Warning: Layout uses the wrong button order for API >= 14: Create a layout-v14/buttonbar.xml file with opposite order: OK button should be on the right (was \"OK | Abort\", should be \"Abort | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:177: Warning: Layout uses the wrong button order for API >= 14: Create a layout-v14/buttonbar.xml file with opposite order: Cancel button should be on the left (was \"Send | Cancel\", should be \"Cancel | Send\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "0 errors, 7 warnings\n" +
+ "",
+
+ lintProject(
+ "minsdk5targetsdk14.xml=>AndroidManifest.xml",
+ "res/layout/buttonbar.xml",
+ "res/values/buttonbar-values.xml"));
+ }
+
+ public void testButtonOrder5() throws Exception {
+ // If the layout is in a non-ICS folder and has the wrong button order,
+ // but there is a v14 version of the layout, don't complain about the non-v14 version
+ sTestIssue = ButtonDetector.ORDER;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "minsdk5targetsdk14.xml=>AndroidManifest.xml",
+ "res/layout/buttonbar.xml",
+ "res/layout/layout1.xml=>res/layout-v14/buttonbar.xml",
+ "res/values/buttonbar-values.xml"));
+ }
+
+ public void testSuppressed() throws Exception {
+ sTestIssue = ButtonDetector.ORDER;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/layout/buttonbar_suppressed.xml",
+ "res/values/buttonbar-values.xml"));
+ }
+
+ public void testButtonOrderRelativeLayout() throws Exception {
+ sTestIssue = ButtonDetector.ORDER;
+ assertEquals(
+ "No warnings.",
+
+ lintProject("res/layout/buttonbar2.xml", "res/values/buttonbar-values.xml"));
+ }
+
+ public void testButtonOrderRelativeLayout2() throws Exception {
+ sTestIssue = ButtonDetector.ORDER;
+ assertEquals(
+ "res/layout/buttonbar3.xml:27: Warning: Cancel button should be on the left [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/layout/buttonbar3.xml",
+ "res/values/buttonbar-values.xml"));
+ }
+
+ public void testButtonOrderRelativeLayout3() throws Exception {
+ sTestIssue = ButtonDetector.ORDER;
+ assertEquals(
+ "No warnings.",
+
+ lintProject("res/layout/buttonbar4.xml", "res/values/buttonbar-values.xml"));
+ }
+
+
+ public void testCase() throws Exception {
+ sTestIssue = ButtonDetector.CASE;
+ assertEquals(
+ "res/values/buttonbar-values.xml:9: Warning: The standard Android way to capitalize Ok is \"OK\" (tip: use @android:string/ok instead) [ButtonCase]\n" +
+ " <string name=\"resume2\"> Ok </string>\n" +
+ " ^\n" +
+ "res/values/buttonbar-values.xml:10: Warning: The standard Android way to capitalize CANCEL is \"Cancel\" (tip: use @android:string/ok instead) [ButtonCase]\n" +
+ " <string name=\"giveup2\">\"CANCEL\"</string>\n" +
+ " ^\n" +
+ "0 errors, 2 warnings\n" +
+ "",
+
+ lintProject("res/layout/buttonbar.xml", "res/values/buttonbar-values.xml"));
+ }
+
+ public void testBack() throws Exception {
+ sTestIssue = ButtonDetector.BACKBUTTON;
+ assertEquals(
+ "res/layout/buttonbar.xml:183: Warning: Back buttons are not standard on Android; see design guide's navigation section [BackButton]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject("res/layout/buttonbar.xml", "res/values/buttonbar-values.xml"));
+ }
+
+ public void testOldApp() throws Exception {
+ // Target SDK < 14 - no warnings on button order
+ sTestIssue = ButtonDetector.ORDER;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "minsdk5targetsdk9.xml=>AndroidManifest.xml",
+ "res/layout/buttonbar.xml",
+ "res/values/buttonbar-values.xml"));
+ }
+
+ public void testEnglishLocales() throws Exception {
+ sTestIssue = ButtonDetector.ORDER;
+ assertEquals(
+ "res/layout-en-rGB/buttonbar.xml:12: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-en-rGB/buttonbar.xml:44: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-en-rGB/buttonbar.xml:92: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-en-rGB/buttonbar.xml:124: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-en-rGB/buttonbar.xml:140: Warning: OK button should be on the right (was \"Ok | CANCEL\", should be \"CANCEL | Ok\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-en-rGB/buttonbar.xml:156: Warning: OK button should be on the right (was \"OK | Abort\", should be \"Abort | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-en-rGB/buttonbar.xml:177: Warning: Cancel button should be on the left (was \"Send | Cancel\", should be \"Cancel | Send\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "0 errors, 7 warnings\n" +
+ "",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/layout/buttonbar.xml=>res/layout-en-rGB/buttonbar.xml",
+ "res/values/buttonbar-values.xml=>res/values-en-rGB/buttonbar-values.xml"));
+ }
+
+ public void testOtherLocales() throws Exception {
+ sTestIssue = ButtonDetector.ORDER;
+ assertEquals(
+ // Hardcoded values only
+ "res/layout-de/buttonbar.xml:12: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout-de/buttonbar.xml:44: Warning: OK button should be on the right (was \"OK | Cancel\", should be \"Cancel | OK\") [ButtonOrder]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "0 errors, 2 warnings\n" +
+ "",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/layout/buttonbar.xml=>res/layout-de/buttonbar.xml",
+ "res/values/buttonbar-values.xml=>res/values-de/buttonbar-values.xml"));
+ }
+
+ public void testOtherLocales2() throws Exception {
+ sTestIssue = ButtonDetector.CASE;
+ assertEquals(
+ "No warnings.",
+
+ lintProject("res/layout/buttonbar.xml=>res/layout-de/buttonbar.xml",
+ "res/values/buttonbar-values.xml=>res/values-de/buttonbar-values.xml"));
+ }
+
+ public void testButtonStyle() throws Exception {
+ sTestIssue = ButtonDetector.STYLE;
+ assertEquals(
+ "res/layout/buttonbar.xml:12: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:17: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:28: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:33: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:44: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:49: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:60: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:65: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:76: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:81: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:92: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:97: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:108: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:113: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:124: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:129: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:140: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:145: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:156: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/buttonbar.xml:161: Warning: Buttons in button bars should be borderless; use style=\"?android:attr/buttonBarButtonStyle\" (and ?android:attr/buttonBarStyle on the parent) [ButtonStyle]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "0 errors, 20 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/layout/buttonbar.xml",
+ "res/layout/buttonbar2.xml",
+ "res/layout/buttonbar3.xml",
+ "res/values/buttonbar-values.xml"));
+ }
+
+ public void testButtonStyleOldMinSdk() throws Exception {
+ sTestIssue = ButtonDetector.STYLE;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "res/layout/buttonbar.xml",
+ "res/layout/buttonbar2.xml",
+ "res/layout/buttonbar3.xml",
+ "res/values/buttonbar-values.xml"));
+ }
+
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ChildCountDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ChildCountDetectorTest.java
new file mode 100644
index 0000000..517ca4d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ChildCountDetectorTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class ChildCountDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ChildCountDetector();
+ }
+
+ public void testChildCount() throws Exception {
+ assertEquals(
+ "res/layout/has_children.xml:3: Warning: A list/grid should have no children declared in XML [AdapterViewChildren]\n" +
+ "<ListView\n" +
+ "^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintFiles("res/layout/has_children.xml"));
+ }
+
+ public void testChildCount2() throws Exception {
+ // A <requestFocus/> tag is okay.
+ assertEquals(
+ "No warnings.",
+ lintFiles("res/layout/has_children2.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ColorUsageDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ColorUsageDetectorTest.java
new file mode 100644
index 0000000..d1a04e1
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ColorUsageDetectorTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class ColorUsageDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ColorUsageDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/WrongColor.java:9: Error: Should pass resolved color instead of resource id here: getResources().getColor(R.color.blue) [ResourceAsColor]\n" +
+ " paint2.setColor(R.color.blue);\n" +
+ " ~~~~~~~~~~~~\n" +
+ "src/test/pkg/WrongColor.java:11: Error: Should pass resolved color instead of resource id here: getResources().getColor(R.color.red) [ResourceAsColor]\n" +
+ " textView.setTextColor(R.color.red);\n" +
+ " ~~~~~~~~~~~\n" +
+ "src/test/pkg/WrongColor.java:12: Error: Should pass resolved color instead of resource id here: getResources().getColor(android.R.color.red) [ResourceAsColor]\n" +
+ " textView.setTextColor(android.R.color.red);\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "3 errors, 0 warnings\n" +
+ "",
+
+ lintProject("src/test/pkg/WrongColor.java.txt=>src/test/pkg/WrongColor.java"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/CommentDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/CommentDetectorTest.java
new file mode 100644
index 0000000..c352962
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/CommentDetectorTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class CommentDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new CommentDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/Hidden.java:11: Warning: STOPSHIP comment found; points to code which must be fixed prior to release [StopShip]\n" +
+ " // STOPSHIP\n" +
+ " ~~~~~~~~\n" +
+ "src/test/pkg/Hidden.java:12: Warning: STOPSHIP comment found; points to code which must be fixed prior to release [StopShip]\n" +
+ " /* We must STOPSHIP! */\n" +
+ " ~~~~~~~~\n" +
+ "src/test/pkg/Hidden.java:5: Warning: Code might be hidden here; found unicode escape sequence which is interpreted as comment end, compiled code follows [EasterEgg]\n" +
+ " /* \\u002a\\u002f static { System.out.println(\"I'm executed on class load\"); } \\u002f\\u002a */\n" +
+ " ~~~~~~~~~~~~\n" +
+ "src/test/pkg/Hidden.java:6: Warning: Code might be hidden here; found unicode escape sequence which is interpreted as comment end, compiled code follows [EasterEgg]\n" +
+ " /* \\u002A\\U002F static { System.out.println(\"I'm executed on class load\"); } \\u002f\\u002a */\n" +
+ " ~~~~~~~~~~~~\n" +
+ "0 errors, 4 warnings\n",
+
+ lintProject("src/test/pkg/Hidden.java.txt=>src/test/pkg/Hidden.java"));
+ }
+
+ public void test2() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject("src/test/pkg/SdCardTest.java.txt=>src/test/pkg/SdCardTest.java"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/CutPasteDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/CutPasteDetectorTest.java
new file mode 100644
index 0000000..df02a41
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/CutPasteDetectorTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class CutPasteDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new CutPasteDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/PasteError.java:15: Warning: The id R.id.textView1 has already been looked up in this method; possible cut & paste error? [CutPasteId]\n" +
+ " View view2 = findViewById(R.id.textView1);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " src/test/pkg/PasteError.java:14: First usage here\n" +
+ "src/test/pkg/PasteError.java:71: Warning: The id R.id.textView1 has already been looked up in this method; possible cut & paste error? [CutPasteId]\n" +
+ " view2 = findViewById(R.id.textView1);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " src/test/pkg/PasteError.java:68: First usage here\n" +
+ "src/test/pkg/PasteError.java:78: Warning: The id R.id.textView1 has already been looked up in this method; possible cut & paste error? [CutPasteId]\n" +
+ " view2 = findViewById(R.id.textView1);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " src/test/pkg/PasteError.java:76: First usage here\n" +
+ "src/test/pkg/PasteError.java:86: Warning: The id R.id.textView1 has already been looked up in this method; possible cut & paste error? [CutPasteId]\n" +
+ " view2 = findViewById(R.id.textView1);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " src/test/pkg/PasteError.java:83: First usage here\n" +
+ "src/test/pkg/PasteError.java:95: Warning: The id R.id.textView1 has already been looked up in this method; possible cut & paste error? [CutPasteId]\n" +
+ " view2 = findViewById(R.id.textView1);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " src/test/pkg/PasteError.java:91: First usage here\n" +
+ "0 errors, 5 warnings\n",
+
+ lintProject("src/test/pkg/PasteError.java.txt=>" +
+ "src/test/pkg/PasteError.java"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/DeprecationDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/DeprecationDetectorTest.java
new file mode 100644
index 0000000..f399014
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/DeprecationDetectorTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class DeprecationDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new DeprecationDetector();
+ }
+
+ public void testApi1() throws Exception {
+ assertEquals(
+ "res/layout/deprecation.xml:2: Warning: AbsoluteLayout is deprecated [Deprecated]\n" +
+ "<AbsoluteLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ "^\n" +
+ "res/layout/deprecation.xml:18: Warning: android:editable is deprecated: Use an <EditText> to make it editable [Deprecated]\n" +
+ " android:editable=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/deprecation.xml:26: Warning: android:editable is deprecated: <EditText> is already editable [Deprecated]\n" +
+ " <EditText android:editable=\"true\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/deprecation.xml:27: Warning: android:editable is deprecated: Use inputType instead [Deprecated]\n" +
+ " <EditText android:editable=\"false\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 4 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "res/layout/deprecation.xml"));
+ }
+
+ public void testApi4() throws Exception {
+ assertEquals(
+ "res/layout/deprecation.xml:2: Warning: AbsoluteLayout is deprecated [Deprecated]\n" +
+ "<AbsoluteLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ "^\n" +
+ "res/layout/deprecation.xml:16: Warning: android:autoText is deprecated: Use inputType instead [Deprecated]\n" +
+ " android:autoText=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/deprecation.xml:17: Warning: android:capitalize is deprecated: Use inputType instead [Deprecated]\n" +
+ " android:capitalize=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/deprecation.xml:18: Warning: android:editable is deprecated: Use an <EditText> to make it editable [Deprecated]\n" +
+ " android:editable=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/deprecation.xml:20: Warning: android:inputMethod is deprecated: Use inputType instead [Deprecated]\n" +
+ " android:inputMethod=\"@+id/foo\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/deprecation.xml:21: Warning: android:numeric is deprecated: Use inputType instead [Deprecated]\n" +
+ " android:numeric=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/deprecation.xml:22: Warning: android:password is deprecated: Use inputType instead [Deprecated]\n" +
+ " android:password=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/deprecation.xml:23: Warning: android:phoneNumber is deprecated: Use inputType instead [Deprecated]\n" +
+ " android:phoneNumber=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/deprecation.xml:26: Warning: android:editable is deprecated: <EditText> is already editable [Deprecated]\n" +
+ " <EditText android:editable=\"true\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/deprecation.xml:27: Warning: android:editable is deprecated: Use inputType instead [Deprecated]\n" +
+ " <EditText android:editable=\"false\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 10 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "res/layout/deprecation.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/DetectMissingPrefixTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/DetectMissingPrefixTest.java
new file mode 100644
index 0000000..e8a6f23
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/DetectMissingPrefixTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class DetectMissingPrefixTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new DetectMissingPrefix();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/layout/namespace.xml:2: Error: Attribute is missing the Android namespace prefix [MissingPrefix]\n" +
+ "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:other=\"http://foo.bar\" android:id=\"@+id/newlinear\" android:orientation=\"vertical\" android:layout_width=\"match_parent\" android:layout_height=\"match_parent\" orientation=\"true\">\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/namespace.xml:3: Error: Attribute is missing the Android namespace prefix [MissingPrefix]\n" +
+ " <Button style=\"@style/setupWizardOuterFrame\" android.text=\"Button\" android:id=\"@+id/button1\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\"></Button>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/namespace.xml:5: Error: Unexpected namespace prefix \"other\" found for tag LinearLayout [MissingPrefix]\n" +
+ " <LinearLayout other:orientation=\"horizontal\"/>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "3 errors, 0 warnings\n",
+
+ lintFiles("res/layout/namespace.xml"));
+ }
+
+ public void testCustomNamespace() throws Exception {
+ assertEquals(
+ "res/layout/namespace2.xml:8: Error: Attribute is missing the Android namespace prefix [MissingPrefix]\n" +
+ " customprefix:orientation=\"vertical\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n" +
+ "",
+
+ lintFiles("res/layout/namespace2.xml"));
+ }
+
+ public void testManifest() throws Exception {
+ assertEquals(
+ "AndroidManifest.xml:4: Error: Attribute is missing the Android namespace prefix [MissingPrefix]\n" +
+ " versionCode=\"1\"\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:11: Error: Attribute is missing the Android namespace prefix [MissingPrefix]\n" +
+ " android.label=\"@string/app_name\" >\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:18: Error: Attribute is missing the Android namespace prefix [MissingPrefix]\n" +
+ " <category name=\"android.intent.category.LAUNCHER\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "3 errors, 0 warnings\n",
+
+ lintFiles("missingprefix.xml=>AndroidManifest.xml"));
+ }
+
+ public void testLayoutAttributes() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles("res/layout/namespace3.xml"));
+ }
+
+ public void testLayoutAttributes2() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles("res/layout/namespace4.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/DosLineEndingDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/DosLineEndingDetectorTest.java
new file mode 100644
index 0000000..3682420
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/DosLineEndingDetectorTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class DosLineEndingDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new DosLineEndingDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/layout/crcrlf.xml:4: Error: Incorrect line ending: found carriage return (\\r) without corresponding newline (\\n) [MangledCRLF]\n" +
+ " android:layout_height=\"match_parent\" >\r\n" +
+ "^\n" +
+ "1 errors, 0 warnings\n",
+ lintProject("res/layout/crcrlf.xml"));
+ }
+
+ public void testIgnore() throws Exception {
+ assertEquals(
+ "No warnings.",
+ lintProject("res/layout/crcrlf_ignore.xml"));
+ }
+
+ public void testNegative() throws Exception {
+ // Make sure we don't get warnings for a correct file
+ assertEquals(
+ "No warnings.",
+ lintProject("res/layout/layout1.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/DuplicateIdDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/DuplicateIdDetectorTest.java
new file mode 100644
index 0000000..72a9035
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/DuplicateIdDetectorTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class DuplicateIdDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new DuplicateIdDetector();
+ }
+
+ public void testDuplicate() throws Exception {
+ assertEquals(
+ "res/layout/duplicate.xml:5: Warning: Duplicate id @+id/android_logo, already defined earlier in this layout [DuplicateIds]\n" +
+ " <ImageButton android:id=\"@+id/android_logo\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:src=\"@drawable/android_button\" android:focusable=\"false\" android:clickable=\"false\" android:layout_weight=\"1.0\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/layout/duplicate.xml:4: @+id/android_logo originally defined here\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintFiles("res/layout/duplicate.xml"));
+ }
+
+ public void testDuplicateChains() throws Exception {
+ assertEquals(
+ "res/layout/layout1.xml:7: Warning: Duplicate id @+id/button1, defined or included multiple times in layout/layout1.xml: [layout/layout1.xml defines @+id/button1, layout/layout1.xml => layout/layout2.xml => layout/layout3.xml defines @+id/button1, layout/layout1.xml => layout/layout2.xml => layout/layout4.xml defines @+id/button1] [DuplicateIncludedIds]\n" +
+ " <include\n" +
+ " ^\n" +
+ " res/layout/layout1.xml:13: Defined here\n" +
+ " res/layout/layout3.xml:8: Defined here, included via layout/layout1.xml => layout/layout2.xml => layout/layout3.xml defines @+id/button1\n" +
+ " res/layout/layout4.xml:8: Defined here, included via layout/layout1.xml => layout/layout2.xml => layout/layout4.xml defines @+id/button1\n" +
+ "res/layout/layout1.xml:7: Warning: Duplicate id @+id/button2, defined or included multiple times in layout/layout1.xml: [layout/layout1.xml defines @+id/button2, layout/layout1.xml => layout/layout2.xml => layout/layout4.xml defines @+id/button2] [DuplicateIncludedIds]\n" +
+ " <include\n" +
+ " ^\n" +
+ " res/layout/layout1.xml:19: Defined here\n" +
+ " res/layout/layout4.xml:14: Defined here, included via layout/layout1.xml => layout/layout2.xml => layout/layout4.xml defines @+id/button2\n" +
+ "res/layout/layout2.xml:18: Warning: Duplicate id @+id/button1, defined or included multiple times in layout/layout2.xml: [layout/layout2.xml => layout/layout3.xml defines @+id/button1, layout/layout2.xml => layout/layout4.xml defines @+id/button1] [DuplicateIncludedIds]\n" +
+ " <include\n" +
+ " ^\n" +
+ " res/layout/layout3.xml:8: Defined here, included via layout/layout2.xml => layout/layout3.xml defines @+id/button1\n" +
+ " res/layout/layout4.xml:8: Defined here, included via layout/layout2.xml => layout/layout4.xml defines @+id/button1\n" +
+ "0 errors, 3 warnings\n" +
+ "",
+
+ // layout1: defines @+id/button1, button2
+ // layout3: defines @+id/button1
+ // layout4: defines @+id/button1, button2
+ // layout1 include layout2
+ // layout2 includes layout3 and layout4
+
+ // Therefore, layout3 and layout4 have no problems
+ // In layout2, there's a duplicate definition of button1 (coming from 3 and 4)
+ // In layout1, there's a duplicate definition of button1 (coming from layout1, 3 and 4)
+ // In layout1, there'sa duplicate definition of button2 (coming from 1 and 4)
+
+ lintProject("res/layout/layout1.xml", "res/layout/layout2.xml",
+ "res/layout/layout3.xml", "res/layout/layout4.xml"));
+ }
+
+ public void testSuppress() throws Exception {
+ assertEquals(
+ "res/layout/layout2.xml:18: Warning: Duplicate id @+id/button1, defined or included multiple times in layout/layout2.xml: [layout/layout2.xml => layout/layout3.xml defines @+id/button1, layout/layout2.xml => layout/layout4.xml defines @+id/button1] [DuplicateIncludedIds]\n" +
+ " <include\n" +
+ " ^\n" +
+ " res/layout/layout3.xml:8: Defined here, included via layout/layout2.xml => layout/layout3.xml defines @+id/button1\n" +
+ " res/layout/layout4.xml:8: Defined here, included via layout/layout2.xml => layout/layout4.xml defines @+id/button1\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "res/layout/layout1_ignore.xml=>res/layout/layout1.xml",
+ "res/layout/layout2.xml",
+ "res/layout/layout3.xml",
+ "res/layout/layout4.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/DuplicateResourceDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/DuplicateResourceDetectorTest.java
new file mode 100644
index 0000000..a4a5a68
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/DuplicateResourceDetectorTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class DuplicateResourceDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new DuplicateResourceDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/values/customattr2.xml:2: Error: ContentFrame has already been defined in this folder [DuplicateDefinition]\n" +
+ " <declare-styleable name=\"ContentFrame\">\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ " res/values/customattr.xml:2: Previously defined here\n" +
+ "res/values/strings2.xml:19: Error: wallpaper_instructions has already been defined in this folder [DuplicateDefinition]\n" +
+ " <string name=\"wallpaper_instructions\">Tap image to set landscape wallpaper</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/values/strings.xml:29: Previously defined here\n" +
+ "2 errors, 0 warnings\n",
+
+ lintProject(
+ "res/values/strings.xml",
+ "res/values-land/strings.xml=>res/values/strings2.xml",
+ "res/values-cs/strings.xml",
+ "res/values/customattr.xml",
+ "res/values/customattr.xml=>res/values/customattr2.xml"));
+ }
+
+ public void testOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/values/strings.xml",
+ "res/values-cs/strings.xml",
+ "res/values-de-rDE/strings.xml",
+ "res/values-es/strings.xml",
+ "res/values-es-rUS/strings.xml",
+ "res/values-land/strings.xml",
+ "res/values-cs/arrays.xml",
+ "res/values-es/donottranslate.xml",
+ "res/values-nl-rNL/strings.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ExtraTextDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ExtraTextDetectorTest.java
new file mode 100644
index 0000000..9f6c2d3
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ExtraTextDetectorTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class ExtraTextDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ExtraTextDetector();
+ }
+
+ public void testBroken() throws Exception {
+ assertEquals(
+ "res/layout/broken.xml:6: Warning: Unexpected text found in layout file: \"ImageButton android:id=\"@+id/android_logo2\" android:layout_width=\"wrap_content\" android:layout_heigh...\" [ExtraText]\n" +
+ " <Button android:text=\"Button\" android:id=\"@+id/button2\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\"></Button>\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject("res/layout/broken.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/FieldGetterDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/FieldGetterDetectorTest.java
new file mode 100644
index 0000000..aa7607f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/FieldGetterDetectorTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class FieldGetterDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new FieldGetterDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/bytecode/GetterTest.java:47: Warning: Calling getter method getFoo1() on self is slower than field access (mFoo1) [FieldGetter]\n" +
+ " getFoo1();\n" +
+ " ~~~~~~~\n" +
+ "src/test/bytecode/GetterTest.java:48: Warning: Calling getter method getFoo2() on self is slower than field access (mFoo2) [FieldGetter]\n" +
+ " getFoo2();\n" +
+ " ~~~~~~~\n" +
+ "src/test/bytecode/GetterTest.java:52: Warning: Calling getter method isBar1() on self is slower than field access (mBar1) [FieldGetter]\n" +
+ " isBar1();\n" +
+ " ~~~~~~\n" +
+ "src/test/bytecode/GetterTest.java:54: Warning: Calling getter method getFoo1() on self is slower than field access (mFoo1) [FieldGetter]\n" +
+ " this.getFoo1();\n" +
+ " ~~~~~~~\n" +
+ "src/test/bytecode/GetterTest.java:55: Warning: Calling getter method getFoo2() on self is slower than field access (mFoo2) [FieldGetter]\n" +
+ " this.getFoo2();\n" +
+ " ~~~~~~~\n" +
+ "0 errors, 5 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "bytecode/GetterTest.java.txt=>src/test/bytecode/GetterTest.java",
+ "bytecode/GetterTest.class.data=>bin/classes/test/bytecode/GetterTest.class"
+ ));
+ }
+
+ public void testPostFroyo() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "apicheck/minsdk10.xml=>AndroidManifest.xml",
+ "bytecode/GetterTest.java.txt=>src/test/bytecode/GetterTest.java",
+ "bytecode/GetterTest.class.data=>bin/classes/test/bytecode/GetterTest.class"
+ ));
+ }
+
+ public void testLibraries() throws Exception {
+ // This tests the infrastructure: it makes sure that we *don't* run this
+ // check in jars that are on the jar library dependency path (testJar() checks
+ // that it *does* work for local jar classes)
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/classpath-lib=>.classpath",
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "bytecode/GetterTest.java.txt=>src/test/bytecode/GetterTest.java",
+ "bytecode/GetterTest.jar.data=>libs/library.jar"
+ ));
+ }
+
+ public void testJar() throws Exception {
+ assertEquals(
+ "src/test/bytecode/GetterTest.java:47: Warning: Calling getter method getFoo1() on self is slower than field access (mFoo1) [FieldGetter]\n" +
+ " getFoo1();\n" +
+ " ~~~~~~~\n" +
+ "src/test/bytecode/GetterTest.java:48: Warning: Calling getter method getFoo2() on self is slower than field access (mFoo2) [FieldGetter]\n" +
+ " getFoo2();\n" +
+ " ~~~~~~~\n" +
+ "src/test/bytecode/GetterTest.java:52: Warning: Calling getter method isBar1() on self is slower than field access (mBar1) [FieldGetter]\n" +
+ " isBar1();\n" +
+ " ~~~~~~\n" +
+ "src/test/bytecode/GetterTest.java:54: Warning: Calling getter method getFoo1() on self is slower than field access (mFoo1) [FieldGetter]\n" +
+ " this.getFoo1();\n" +
+ " ~~~~~~~\n" +
+ "src/test/bytecode/GetterTest.java:55: Warning: Calling getter method getFoo2() on self is slower than field access (mFoo2) [FieldGetter]\n" +
+ " this.getFoo2();\n" +
+ " ~~~~~~~\n" +
+ "0 errors, 5 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/classpath-jar=>.classpath",
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "bytecode/GetterTest.java.txt=>src/test/bytecode/GetterTest.java",
+ "bytecode/GetterTest.jar.data=>bin/classes.jar"
+ ));
+ }
+
+ public void testTruncatedData() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/classpath-jar=>.classpath",
+ "bytecode/GetterTest.jar.data=>bin/test/pkg/bogus.class"
+ ));
+ }
+
+ public void testCornerCases() throws Exception {
+ assertEquals(
+ "src/test/pkg/TestFieldGetter.java:21: Warning: Calling getter method getPath() on self is slower than field access (path) [FieldGetter]\n" +
+ " getPath(); // Should be flagged\n" +
+ " ~~~~~~~\n" +
+ "0 errors, 1 warnings\n",
+
+ lintProject(
+ "bytecode/classpath-jar=>.classpath",
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "bytecode/TestFieldGetter.java.txt=>src/test/pkg/TestFieldGetter.java",
+ "bytecode/TestFieldGetter.class.data=>bin/classes/test/pkg/TestFieldGetter.class"
+ ));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/FragmentDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/FragmentDetectorTest.java
new file mode 100644
index 0000000..f732f71
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/FragmentDetectorTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class FragmentDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new FragmentDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/FragmentTest.java:10: Warning: This fragment class should be public (test.pkg.FragmentTest.Fragment1) [ValidFragment]\n" +
+ " private static class Fragment1 extends Fragment {\n" +
+ " ^\n" +
+ "src/test/pkg/FragmentTest.java:15: Warning: This fragment inner class should be static (test.pkg.FragmentTest.Fragment2) [ValidFragment]\n" +
+ " public class Fragment2 extends Fragment {\n" +
+ " ^\n" +
+ "src/test/pkg/FragmentTest.java:21: Warning: The default constructor must be public [ValidFragment]\n" +
+ " private Fragment3() {\n" +
+ " ~~~~~~~~~\n" +
+ "src/test/pkg/FragmentTest.java:26: Warning: This fragment should provide a default constructor (a public constructor with no arguments) (test.pkg.FragmentTest.Fragment4) [ValidFragment]\n" +
+ " public static class Fragment4 extends Fragment {\n" +
+ " ~~~~~~~~~\n" +
+ "src/test/pkg/FragmentTest.java:27: Warning: Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead [ValidFragment]\n" +
+ " private Fragment4(int dummy) {\n" +
+ " ~~~~~~~~~\n" +
+ "src/test/pkg/FragmentTest.java:36: Warning: Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead [ValidFragment]\n" +
+ " public Fragment5(int dummy) {\n" +
+ " ~~~~~~~~~\n" +
+ "0 errors, 6 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/FragmentTest$Fragment1.class.data=>bin/classes/test/pkg/FragmentTest$Fragment1.class",
+ "bytecode/FragmentTest$Fragment2.class.data=>bin/classes/test/pkg/FragmentTest$Fragment2.class",
+ "bytecode/FragmentTest$Fragment3.class.data=>bin/classes/test/pkg/FragmentTest$Fragment3.class",
+ "bytecode/FragmentTest$Fragment4.class.data=>bin/classes/test/pkg/FragmentTest$Fragment4.class",
+ "bytecode/FragmentTest$Fragment5.class.data=>bin/classes/test/pkg/FragmentTest$Fragment5.class",
+ "bytecode/FragmentTest$Fragment6.class.data=>bin/classes/test/pkg/FragmentTest$Fragment6.class",
+ "bytecode/FragmentTest$NotAFragment.class.data=>bin/classes/test/pkg/FragmentTest$NotAFragment.class",
+ "bytecode/FragmentTest.java.txt=>src/test/pkg/FragmentTest.java"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/GridLayoutDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/GridLayoutDetectorTest.java
new file mode 100644
index 0000000..dee52e1
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/GridLayoutDetectorTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class GridLayoutDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new GridLayoutDetector();
+ }
+
+ public void testGridLayout1() throws Exception {
+ assertEquals(
+ "res/layout/gridlayout.xml:36: Error: Column attribute (3) exceeds declared grid column count (2) [GridLayout]\n" +
+ " android:layout_column=\"3\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n" +
+ "",
+ lintFiles("res/layout/gridlayout.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/HandlerDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/HandlerDetectorTest.java
new file mode 100644
index 0000000..1e9350c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/HandlerDetectorTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class HandlerDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new HandlerDetector();
+ }
+
+ public void testRegistered() throws Exception {
+ assertEquals(
+ "src/test/pkg/HandlerTest.java:12: Warning: This Handler class should be static or leaks might occur (test.pkg.HandlerTest.Inner) [HandlerLeak]\n" +
+ " public class Inner extends Handler { // ERROR\n" +
+ " ~~~~~\n" +
+ "src/test/pkg/HandlerTest.java:18: Warning: This Handler class should be static or leaks might occur (test.pkg.HandlerTest.1) [HandlerLeak]\n" +
+ " Handler anonymous = new Handler() { // ERROR\n" +
+ " ~~~~~~~\n" +
+ "0 errors, 2 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/HandlerTest.java.txt=>src/test/pkg/HandlerTest.java",
+ "bytecode/HandlerTest.class.data=>bin/classes/test/pkg/HandlerTest.class",
+ "bytecode/HandlerTest$Inner.class.data=>bin/classes/test/pkg/HandlerTest$Inner.class",
+ "bytecode/HandlerTest$StaticInner.class.data=>bin/classes/test/pkg/HandlerTest$StaticInner.class",
+ "bytecode/HandlerTest$1.class.data=>bin/classes/test/pkg/HandlerTest$1.class"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/HardcodedDebugModeDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/HardcodedDebugModeDetectorTest.java
new file mode 100644
index 0000000..edb6c50
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/HardcodedDebugModeDetectorTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class HardcodedDebugModeDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new HardcodedDebugModeDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "AndroidManifest.xml:10: Warning: Avoid hardcoding the debug mode; leaving it out allows debug and release builds to automatically assign one [HardcodedDebugMode]\n" +
+ " android:debuggable=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject("debuggable.xml=>AndroidManifest.xml"));
+ }
+
+ public void testOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+ lintProject("AndroidManifest.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/HardcodedValuesDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/HardcodedValuesDetectorTest.java
new file mode 100644
index 0000000..b326fd4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/HardcodedValuesDetectorTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class HardcodedValuesDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new HardcodedValuesDetector();
+ }
+
+ public void testStrings() throws Exception {
+ assertEquals(
+ "res/layout/accessibility.xml:3: Warning: [I18N] Hardcoded string \"Button\", should use @string resource [HardcodedText]\n" +
+ " <Button android:text=\"Button\" android:id=\"@+id/button1\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\"></Button>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/accessibility.xml:6: Warning: [I18N] Hardcoded string \"Button\", should use @string resource [HardcodedText]\n" +
+ " <Button android:text=\"Button\" android:id=\"@+id/button2\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\"></Button>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 2 warnings\n",
+
+ lintFiles("res/layout/accessibility.xml"));
+ }
+
+ public void testMenus() throws Exception {
+ assertEquals(
+ "res/menu/menu.xml:7: Warning: [I18N] Hardcoded string \"My title 1\", should use @string resource [HardcodedText]\n" +
+ " android:title=\"My title 1\">\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/menu/menu.xml:13: Warning: [I18N] Hardcoded string \"My title 2\", should use @string resource [HardcodedText]\n" +
+ " android:title=\"My title 2\">\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 2 warnings\n",
+
+ lintFiles("res/menu/menu.xml"));
+ }
+
+ public void testMenusOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+ lintFiles("res/menu/titles.xml"));
+ }
+
+ public void testSuppress() throws Exception {
+ // All but one errors in the file contain ignore attributes - direct, inherited
+ // and lists
+ assertEquals(
+ "res/layout/ignores.xml:61: Warning: [I18N] Hardcoded string \"Hardcoded\", should use @string resource [HardcodedText]\n" +
+ " android:text=\"Hardcoded\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintFiles("res/layout/ignores.xml"));
+ }
+
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/IconDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/IconDetectorTest.java
new file mode 100644
index 0000000..e2c20ba
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/IconDetectorTest.java
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.client.api.LintClient;
+import com.android.tools.lint.client.api.LintDriver;
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Issue;
+import com.android.tools.lint.detector.api.Project;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+@SuppressWarnings("javadoc")
+public class IconDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new IconDetector();
+ }
+
+ private Set<Issue> mEnabled = new HashSet<Issue>();
+ private boolean mAbbreviate;
+
+ private static Set<Issue> ALL = new HashSet<Issue>();
+ static {
+ ALL.add(IconDetector.DUPLICATES_CONFIGURATIONS);
+ ALL.add(IconDetector.DUPLICATES_NAMES);
+ ALL.add(IconDetector.GIF_USAGE);
+ ALL.add(IconDetector.ICON_DENSITIES);
+ ALL.add(IconDetector.ICON_DIP_SIZE);
+ ALL.add(IconDetector.ICON_EXTENSION);
+ ALL.add(IconDetector.ICON_LOCATION);
+ ALL.add(IconDetector.ICON_MISSING_FOLDER);
+ ALL.add(IconDetector.ICON_NODPI);
+ ALL.add(IconDetector.ICON_COLORS);
+ ALL.add(IconDetector.ICON_XML_AND_PNG);
+ ALL.add(IconDetector.ICON_LAUNCHER_SHAPE);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mAbbreviate = true;
+ }
+
+ @Override
+ protected void configureDriver(LintDriver driver) {
+ driver.setAbbreviating(mAbbreviate);
+ }
+
+ @Override
+ protected TestConfiguration getConfiguration(LintClient client, Project project) {
+ return new TestConfiguration(client, project, null) {
+ @Override
+ public boolean isEnabled(Issue issue) {
+ return super.isEnabled(issue) && mEnabled.contains(issue);
+ }
+ };
+ }
+
+ public void test() throws Exception {
+ mEnabled = ALL;
+ assertEquals(
+ "res/drawable-mdpi/sample_icon.gif: Warning: Using the .gif format for bitmaps is discouraged [GifUsage]\n" +
+ "res/drawable/ic_launcher.png: Warning: The ic_launcher.png icon has identical contents in the following configuration folders: drawable-mdpi, drawable [IconDuplicatesConfig]\n" +
+ " res/drawable-mdpi/ic_launcher.png: <No location-specific message\n" +
+ "res/drawable/ic_launcher.png: Warning: Found bitmap drawable res/drawable/ic_launcher.png in densityless folder [IconLocation]\n" +
+ "res/drawable-hdpi: Warning: Missing the following drawables in drawable-hdpi: sample_icon.gif (found in drawable-mdpi) [IconDensities]\n" +
+ "res: Warning: Missing density variation folders in res: drawable-xhdpi [IconMissingDensityFolder]\n" +
+ "0 errors, 5 warnings\n" +
+ "",
+
+ lintProject(
+ // Use minSDK4 to ensure that we get warnings about missing drawables
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "res/drawable/ic_launcher.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher.png",
+ "res/drawable-mdpi/sample_icon.gif",
+ // Make a dummy file named .svn to make sure it doesn't get seen as
+ // an icon name
+ "res/drawable-mdpi/sample_icon.gif=>res/drawable-hdpi/.svn",
+ "res/drawable-hdpi/ic_launcher.png"));
+ }
+
+ public void testMixed() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_XML_AND_PNG);
+ assertEquals(
+ "res/drawable/background.xml: Warning: The following images appear both as density independent .xml files and as bitmap files: res/drawable-mdpi/background.png, res/drawable/background.xml [IconXmlAndPng]\n" +
+ " res/drawable-mdpi/background.png: <No location-specific message\n" +
+ "0 errors, 1 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "apicheck/minsdk4.xml=>res/drawable/background.xml",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/background.png"));
+ }
+
+ public void testApi1() throws Exception {
+ mEnabled = ALL;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ // manifest file which specifies uses sdk = 2
+ "apicheck/minsdk2.xml=>AndroidManifest.xml",
+ "res/drawable/ic_launcher.png"));
+ }
+
+ public void test2() throws Exception {
+ mEnabled = ALL;
+ assertEquals(
+ "res/drawable-hdpi/other.9.png: Warning: The following unrelated icon files have identical contents: appwidget_bg.9.png, other.9.png [IconDuplicates]\n" +
+ " res/drawable-hdpi/appwidget_bg.9.png: <No location-specific message\n" +
+ "res/drawable-hdpi/unrelated.png: Warning: The following unrelated icon files have identical contents: ic_launcher.png, unrelated.png [IconDuplicates]\n" +
+ " res/drawable-hdpi/ic_launcher.png: <No location-specific message\n" +
+ "res: Warning: Missing density variation folders in res: drawable-mdpi, drawable-xhdpi [IconMissingDensityFolder]\n" +
+ "0 errors, 3 warnings\n" +
+ "",
+
+ lintProject(
+ "res/drawable-hdpi/unrelated.png",
+ "res/drawable-hdpi/appwidget_bg.9.png",
+ "res/drawable-hdpi/appwidget_bg_focus.9.png",
+ "res/drawable-hdpi/other.9.png",
+ "res/drawable-hdpi/ic_launcher.png"
+ ));
+ }
+
+ public void testNoDpi() throws Exception {
+ mEnabled = ALL;
+ assertEquals(
+ "res/drawable-mdpi/frame.png: Warning: The following images appear in both -nodpi and in a density folder: frame.png [IconNoDpi]\n" +
+ "res/drawable-xlarge-nodpi-v11/frame.png: Warning: The frame.png icon has identical contents in the following configuration folders: drawable-mdpi, drawable-nodpi, drawable-xlarge-nodpi-v11 [IconDuplicatesConfig]\n" +
+ " res/drawable-nodpi/frame.png: <No location-specific message\n" +
+ " res/drawable-mdpi/frame.png: <No location-specific message\n" +
+ "res: Warning: Missing density variation folders in res: drawable-hdpi, drawable-xhdpi [IconMissingDensityFolder]\n" +
+ "0 errors, 3 warnings\n" +
+ "",
+
+ lintProject(
+ "res/drawable-mdpi/frame.png",
+ "res/drawable-nodpi/frame.png",
+ "res/drawable-xlarge-nodpi-v11/frame.png"));
+ }
+
+ public void testNoDpi2() throws Exception {
+ mEnabled = ALL;
+ // Having additional icon names in the no-dpi folder should not cause any complaints
+ assertEquals(
+ "res/drawable-xhdpi/frame.png: Warning: The image frame.png varies significantly in its density-independent (dip) size across the various density versions: drawable-ldpi/frame.png: 629x387 dp (472x290 px), drawable-mdpi/frame.png: 472x290 dp (472x290 px), drawable-hdpi/frame.png: 315x193 dp (472x290 px), drawable-xhdpi/frame.png: 236x145 dp (472x290 px) [IconDipSize]\n" +
+ " res/drawable-hdpi/frame.png: <No location-specific message\n" +
+ " res/drawable-mdpi/frame.png: <No location-specific message\n" +
+ " res/drawable-ldpi/frame.png: <No location-specific message\n" +
+ "res/drawable-xhdpi/frame.png: Warning: The following unrelated icon files have identical contents: frame.png, frame.png, frame.png, file1.png, file2.png, frame.png [IconDuplicates]\n" +
+ " res/drawable-nodpi/file2.png: <No location-specific message\n" +
+ " res/drawable-nodpi/file1.png: <No location-specific message\n" +
+ " res/drawable-mdpi/frame.png: <No location-specific message\n" +
+ " res/drawable-ldpi/frame.png: <No location-specific message\n" +
+ " res/drawable-hdpi/frame.png: <No location-specific message\n" +
+ "0 errors, 2 warnings\n" +
+ "",
+
+ lintProject(
+ "res/drawable-mdpi/frame.png=>res/drawable-mdpi/frame.png",
+ "res/drawable-mdpi/frame.png=>res/drawable-hdpi/frame.png",
+ "res/drawable-mdpi/frame.png=>res/drawable-ldpi/frame.png",
+ "res/drawable-mdpi/frame.png=>res/drawable-xhdpi/frame.png",
+ "res/drawable-mdpi/frame.png=>res/drawable-nodpi/file1.png",
+ "res/drawable-mdpi/frame.png=>res/drawable-nodpi/file2.png"));
+ }
+
+ public void testNoDpiMix() throws Exception {
+ mEnabled = ALL;
+ assertEquals(
+ "res/drawable-mdpi/frame.xml: Warning: The following images appear in both -nodpi and in a density folder: frame.png, frame.xml [IconNoDpi]\n" +
+ " res/drawable-mdpi/frame.png: <No location-specific message\n" +
+ "res/drawable-nodpi/frame.xml: Warning: The following images appear both as density independent .xml files and as bitmap files: res/drawable-mdpi/frame.png, res/drawable-nodpi/frame.xml [IconXmlAndPng]\n" +
+ " res/drawable-mdpi/frame.png: <No location-specific message\n" +
+ "res: Warning: Missing density variation folders in res: drawable-hdpi, drawable-xhdpi [IconMissingDensityFolder]\n" +
+ "0 errors, 3 warnings\n",
+
+ lintProject(
+ "res/drawable-mdpi/frame.png",
+ "res/drawable/states.xml=>res/drawable-nodpi/frame.xml"));
+ }
+
+
+ public void testMixedFormat() throws Exception {
+ mEnabled = ALL;
+ // Test having a mixture of .xml and .png resources for the same name
+ // Make sure we don't get:
+ // drawable-hdpi: Warning: Missing the following drawables in drawable-hdpi: f.png (found in drawable-mdpi)
+ // drawable-xhdpi: Warning: Missing the following drawables in drawable-xhdpi: f.png (found in drawable-mdpi)
+ assertEquals(
+ "res/drawable-xhdpi/f.xml: Warning: The following images appear both as density independent .xml files and as bitmap files: res/drawable-hdpi/f.xml, res/drawable-mdpi/f.png [IconXmlAndPng]\n" +
+ " res/drawable-mdpi/f.png: <No location-specific message\n" +
+ " res/drawable-hdpi/f.xml: <No location-specific message\n" +
+ "0 errors, 1 warnings\n",
+
+ lintProject(
+ "res/drawable-mdpi/frame.png=>res/drawable-mdpi/f.png",
+ "res/drawable/states.xml=>res/drawable-hdpi/f.xml",
+ "res/drawable/states.xml=>res/drawable-xhdpi/f.xml"));
+ }
+
+ public void testMisleadingFileName() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_EXTENSION);
+ assertEquals(
+ "res/drawable-mdpi/frame.gif: Warning: Misleading file extension; named .gif but the file format is png [IconExtension]\n" +
+ "res/drawable-mdpi/frame.jpg: Warning: Misleading file extension; named .jpg but the file format is png [IconExtension]\n" +
+ "res/drawable-mdpi/myjpg.png: Warning: Misleading file extension; named .png but the file format is JPEG [IconExtension]\n" +
+ "res/drawable-mdpi/sample_icon.jpeg: Warning: Misleading file extension; named .jpeg but the file format is gif [IconExtension]\n" +
+ "res/drawable-mdpi/sample_icon.jpg: Warning: Misleading file extension; named .jpg but the file format is gif [IconExtension]\n" +
+ "res/drawable-mdpi/sample_icon.png: Warning: Misleading file extension; named .png but the file format is gif [IconExtension]\n" +
+ "0 errors, 6 warnings\n",
+
+ lintProject(
+ "res/drawable-mdpi/sample_icon.jpg=>res/drawable-mdpi/myjpg.jpg", // VALID
+ "res/drawable-mdpi/sample_icon.jpg=>res/drawable-mdpi/myjpg.jpeg", // VALID
+ "res/drawable-mdpi/frame.png=>res/drawable-mdpi/frame.gif",
+ "res/drawable-mdpi/frame.png=>res/drawable-mdpi/frame.jpg",
+ "res/drawable-mdpi/sample_icon.jpg=>res/drawable-mdpi/myjpg.png",
+ "res/drawable-mdpi/sample_icon.gif=>res/drawable-mdpi/sample_icon.jpg",
+ "res/drawable-mdpi/sample_icon.gif=>res/drawable-mdpi/sample_icon.jpeg",
+ "res/drawable-mdpi/sample_icon.gif=>res/drawable-mdpi/sample_icon.png"));
+ }
+
+ public void testColors() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_COLORS);
+ assertEquals(
+ "res/drawable-mdpi/ic_menu_my_action.png: Warning: Action Bar icons should use a single gray color (#333333 for light themes (with 60%/30% opacity for enabled/disabled), and #FFFFFF with opacity 80%/30% for dark themes [IconColors]\n" +
+ "res/drawable-mdpi-v11/ic_stat_my_notification.png: Warning: Notification icons must be entirely white [IconColors]\n" +
+ "res/drawable-mdpi-v9/ic_stat_my_notification2.png: Warning: Notification icons must be entirely white [IconColors]\n" +
+ "0 errors, 3 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_menu_my_action.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi-v11/ic_stat_my_notification.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi-v9/ic_stat_my_notification2.png",
+ "res/drawable-mdpi/ic_menu_add_clip_normal.png")); // OK
+ }
+
+ public void testNotActionBarIcons() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_COLORS);
+ assertEquals(
+ "No warnings.",
+
+ // No Java code designates the menu as an action bar menu
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/menu/menu.xml",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon1.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon2.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon3.png", // Not action bar
+ "res/drawable-mdpi/ic_menu_add_clip_normal.png")); // OK
+ }
+
+ public void testActionBarIcons() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_COLORS);
+ assertEquals(
+ "res/drawable-mdpi/icon1.png: Warning: Action Bar icons should use a single gray color (#333333 for light themes (with 60%/30% opacity for enabled/disabled), and #FFFFFF with opacity 80%/30% for dark themes [IconColors]\n" +
+ "res/drawable-mdpi/icon2.png: Warning: Action Bar icons should use a single gray color (#333333 for light themes (with 60%/30% opacity for enabled/disabled), and #FFFFFF with opacity 80%/30% for dark themes [IconColors]\n" +
+ "0 errors, 2 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/menu/menu.xml",
+ "src/test/pkg/ActionBarTest.java.txt=>src/test/pkg/ActionBarTest.java",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon1.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon2.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon3.png", // Not action bar
+ "res/drawable-mdpi/ic_menu_add_clip_normal.png")); // OK
+ }
+
+ public void testOkActionBarIcons() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_COLORS);
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/menu/menu.xml",
+ "res/drawable-mdpi/ic_menu_add_clip_normal.png=>res/drawable-mdpi/icon1.png",
+ "res/drawable-mdpi/ic_menu_add_clip_normal.png=>res/drawable-mdpi/icon2.png"));
+ }
+
+ public void testNotificationIcons() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_COLORS);
+ assertEquals(
+ "res/drawable-mdpi/icon1.png: Warning: Notification icons must be entirely white [IconColors]\n" +
+ "res/drawable-mdpi/icon2.png: Warning: Notification icons must be entirely white [IconColors]\n" +
+ "res/drawable-mdpi/icon3.png: Warning: Notification icons must be entirely white [IconColors]\n" +
+ "res/drawable-mdpi/icon4.png: Warning: Notification icons must be entirely white [IconColors]\n" +
+ "res/drawable-mdpi/icon5.png: Warning: Notification icons must be entirely white [IconColors]\n" +
+ "0 errors, 5 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "src/test/pkg/NotificationTest.java.txt=>src/test/pkg/NotificationTest.java",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon1.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon2.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon3.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon4.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon5.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon6.png", // not a notification
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon7.png", // ditto
+ "res/drawable-mdpi/ic_menu_add_clip_normal.png")); // OK
+ }
+
+ public void testOkNotificationIcons() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_COLORS);
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "src/test/pkg/NotificationTest.java.txt=>src/test/pkg/NotificationTest.java",
+ "res/drawable-mdpi/ic_menu_add_clip_normal.png=>res/drawable-mdpi/icon1.png",
+ "res/drawable-mdpi/ic_menu_add_clip_normal.png=>res/drawable-mdpi/icon2.png",
+ "res/drawable-mdpi/ic_menu_add_clip_normal.png=>res/drawable-mdpi/icon3.png",
+ "res/drawable-mdpi/ic_menu_add_clip_normal.png=>res/drawable-mdpi/icon4.png",
+ "res/drawable-mdpi/ic_menu_add_clip_normal.png=>res/drawable-mdpi/icon5.png"));
+ }
+
+ public void testExpectedSize() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_EXPECTED_SIZE);
+ assertEquals(
+ "res/drawable-mdpi/ic_launcher.png: Warning: Incorrect icon size for drawable-mdpi/ic_launcher.png: expected 48x48, but was 24x24 [IconExpectedSize]\n" +
+ "res/drawable-mdpi/icon1.png: Warning: Incorrect icon size for drawable-mdpi/icon1.png: expected 32x32, but was 48x48 [IconExpectedSize]\n" +
+ "res/drawable-mdpi/icon3.png: Warning: Incorrect icon size for drawable-mdpi/icon3.png: expected 24x24, but was 48x48 [IconExpectedSize]\n" +
+ "0 errors, 3 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "src/test/pkg/NotificationTest.java.txt=>src/test/pkg/NotificationTest.java",
+ "res/menu/menu.xml",
+ "src/test/pkg/ActionBarTest.java.txt=>src/test/pkg/ActionBarTest.java",
+
+ // 3 wrong-sized icons:
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon1.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/icon3.png",
+ "res/drawable-mdpi/stat_notify_alarm.png=>res/drawable-mdpi/ic_launcher.png",
+
+ // OK sizes
+ "res/drawable-mdpi/ic_menu_add_clip_normal.png=>res/drawable-mdpi/icon2.png",
+ "res/drawable-mdpi/stat_notify_alarm.png=>res/drawable-mdpi/icon4.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher2.png"
+ ));
+ }
+
+ public void testAbbreviate() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_DENSITIES);
+ assertEquals(
+ "res/drawable-hdpi: Warning: Missing the following drawables in drawable-hdpi: " +
+ "ic_launcher10.png, ic_launcher11.png, ic_launcher12.png, ic_launcher2.png, " +
+ "ic_launcher3.png... (6 more) [IconDensities]\n" +
+ "res/drawable-xhdpi: Warning: Missing the following drawables in drawable-xhdpi: " +
+ "ic_launcher10.png, ic_launcher11.png, ic_launcher12.png, ic_launcher2.png, " +
+ "ic_launcher3.png... (6 more) [IconDensities]\n" +
+ "0 errors, 2 warnings\n",
+
+ lintProject(
+ // Use minSDK4 to ensure that we get warnings about missing drawables
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "res/drawable/ic_launcher.png=>res/drawable-hdpi/ic_launcher1.png",
+ "res/drawable/ic_launcher.png=>res/drawable-xhdpi/ic_launcher1.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher1.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher2.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher3.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher4.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher5.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher6.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher7.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher8.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher9.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher10.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher11.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher12.png"
+ ));
+ }
+
+
+ public void testShowAll() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_DENSITIES);
+ mAbbreviate = false;
+ assertEquals(
+ "res/drawable-hdpi: Warning: Missing the following drawables in drawable-hdpi: " +
+ "ic_launcher10.png, ic_launcher11.png, ic_launcher12.png, ic_launcher2.png, " +
+ "ic_launcher3.png, ic_launcher4.png, ic_launcher5.png, ic_launcher6.png, " +
+ "ic_launcher7.png, ic_launcher8.png, ic_launcher9.png [IconDensities]\n" +
+ "res/drawable-xhdpi: Warning: Missing the following drawables in drawable-xhdpi: " +
+ "ic_launcher10.png, ic_launcher11.png, ic_launcher12.png, ic_launcher2.png," +
+ " ic_launcher3.png, ic_launcher4.png, ic_launcher5.png, ic_launcher6.png, " +
+ "ic_launcher7.png, ic_launcher8.png, ic_launcher9.png [IconDensities]\n" +
+ "0 errors, 2 warnings\n",
+
+ lintProject(
+ // Use minSDK4 to ensure that we get warnings about missing drawables
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "res/drawable/ic_launcher.png=>res/drawable-hdpi/ic_launcher1.png",
+ "res/drawable/ic_launcher.png=>res/drawable-xhdpi/ic_launcher1.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher1.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher2.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher3.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher4.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher5.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher6.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher7.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher8.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher9.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher10.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher11.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher12.png"
+ ));
+ }
+
+ public void testIgnoreMissingFolders() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_DENSITIES);
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ // Use minSDK4 to ensure that we get warnings about missing drawables
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "ignoremissing.xml=>lint.xml",
+ "res/drawable/ic_launcher.png=>res/drawable-hdpi/ic_launcher1.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher1.png",
+ "res/drawable/ic_launcher.png=>res/drawable-mdpi/ic_launcher2.png"
+ ));
+ }
+
+ public void testSquareLauncher() throws Exception {
+ mEnabled = Collections.singleton(IconDetector.ICON_LAUNCHER_SHAPE);
+ assertEquals(
+ "res/drawable-hdpi/ic_launcher_filled.png: Warning: Launcher icons should not fill every pixel of their square region; see the design guide for details [IconLauncherShape]\n" +
+ "0 errors, 1 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "res/drawable-hdpi/filled.png=>res/drawable-hdpi/ic_launcher_filled.png",
+ "res/drawable-mdpi/sample_icon.gif=>res/drawable-mdpi/ic_launcher_2.gif"
+ ));
+ }
+} \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/InefficientWeightDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/InefficientWeightDetectorTest.java
new file mode 100644
index 0000000..644bb10
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/InefficientWeightDetectorTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class InefficientWeightDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new InefficientWeightDetector();
+ }
+
+ public void testWeights() throws Exception {
+ assertEquals(
+ "res/layout/inefficient_weight.xml:10: Warning: Use a layout_width of 0dip instead of match_parent for better performance [InefficientWeight]\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/inefficient_weight.xml:24: Warning: Use a layout_height of 0dip instead of wrap_content for better performance [InefficientWeight]\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 2 warnings\n" +
+ "",
+ lintFiles("res/layout/inefficient_weight.xml"));
+ }
+
+ public void testWeights2() throws Exception {
+ assertEquals(
+ "res/layout/nested_weights.xml:23: Warning: Nested weights are bad for performance [NestedWeights]\n" +
+ " android:layout_weight=\"1\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintFiles("res/layout/nested_weights.xml"));
+ }
+
+ public void testWeights3() throws Exception {
+ assertEquals(
+ "res/layout/baseline_weights.xml:2: Warning: Set android:baselineAligned=\"false\" on this element for better performance [DisableBaselineAlignment]\n" +
+ "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ "^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintFiles("res/layout/baseline_weights.xml"));
+ }
+
+ public void testWeights4() throws Exception {
+ assertEquals(
+ "res/layout/activity_item_two_pane.xml:1: Warning: Set android:baselineAligned=\"false\" on this element for better performance [DisableBaselineAlignment]\n" +
+ "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ "^\n" +
+ "0 errors, 1 warnings\n",
+ lintFiles("res/layout/activity_item_two_pane.xml"));
+ }
+
+ public void testNoVerticalWeights3() throws Exception {
+ // Orientation=vertical
+ assertEquals(
+ "No warnings.",
+ lintFiles("res/layout/baseline_weights2.xml"));
+ }
+
+ public void testNoVerticalWeights4() throws Exception {
+ // Orientation not specified ==> horizontal
+ assertEquals(
+ "res/layout/baseline_weights3.xml:2: Warning: Set android:baselineAligned=\"false\" on this element for better performance [DisableBaselineAlignment]\n" +
+ "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ "^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintFiles("res/layout/baseline_weights3.xml"));
+ }
+
+ public void testSuppressed() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles("res/layout/inefficient_weight2.xml"));
+ }
+
+ public void testNestedWeights() throws Exception {
+ // Regression test for http://code.google.com/p/android/issues/detail?id=22889
+ // (Comment 8)
+ assertEquals(
+ "No warnings.",
+
+ lintFiles("res/layout/nested_weights2.xml"));
+ }
+
+ public void testWrong0Dp() throws Exception {
+ assertEquals(
+ "res/layout/wrong0dp.xml:19: Error: Suspicious size: this will make the view invisible, should be used with layout_weight [Suspicious0dp]\n" +
+ " android:layout_width=\"0dp\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrong0dp.xml:25: Error: Suspicious size: this will make the view invisible, should be used with layout_weight [Suspicious0dp]\n" +
+ " android:layout_height=\"0dp\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrong0dp.xml:34: Error: Suspicious size: this will make the view invisible, probably intended for layout_height [Suspicious0dp]\n" +
+ " android:layout_width=\"0dp\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrong0dp.xml:67: Error: Suspicious size: this will make the view invisible, probably intended for layout_width [Suspicious0dp]\n" +
+ " android:layout_height=\"0dp\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrong0dp.xml:90: Error: Suspicious size: this will make the view invisible, probably intended for layout_width [Suspicious0dp]\n" +
+ " android:layout_height=\"0dp\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "5 errors, 0 warnings\n",
+
+ lintFiles("res/layout/wrong0dp.xml"));
+ }
+
+
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/InvalidPackageDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/InvalidPackageDetectorTest.java
new file mode 100644
index 0000000..b634255
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/InvalidPackageDetectorTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class InvalidPackageDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new InvalidPackageDetector();
+ }
+
+ public void testUnsupportedJavaLibraryCode() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=39109
+ assertEquals(
+ "libs/unsupported.jar: Error: Invalid package reference in library; not included in Android: java.awt. Referenced from test.pkg.LibraryClass. [InvalidPackage]\n" +
+ "libs/unsupported.jar: Error: Invalid package reference in library; not included in Android: javax.swing. Referenced from test.pkg.LibraryClass. [InvalidPackage]\n" +
+ "2 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "apicheck/layout.xml=>res/layout/layout.xml",
+ "apicheck/themes.xml=>res/values/themes.xml",
+ "apicheck/themes.xml=>res/color/colors.xml",
+ "apicheck/unsupported.jar.data=>libs/unsupported.jar"
+ ));
+ }
+
+ public void testOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk2.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest.class.data=>bin/classes/foo/bar/ApiCallTest.class",
+ "bytecode/GetterTest.jar.data=>libs/GetterTest.jar",
+ "bytecode/classes.jar=>libs/classes.jar"
+ ));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/JavaPerformanceDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/JavaPerformanceDetectorTest.java
new file mode 100644
index 0000000..9705dff
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/JavaPerformanceDetectorTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class JavaPerformanceDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new JavaPerformanceDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/JavaPerformanceTest.java:28: Warning: Avoid object allocations during draw/layout operations (preallocate and reuse instead) [DrawAllocation]\n" +
+ " new String(\"foo\");\n" +
+ " ~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:29: Warning: Avoid object allocations during draw/layout operations (preallocate and reuse instead) [DrawAllocation]\n" +
+ " String s = new String(\"bar\");\n" +
+ " ~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:103: Warning: Avoid object allocations during draw/layout operations (preallocate and reuse instead) [DrawAllocation]\n" +
+ " new String(\"flag me\");\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:109: Warning: Avoid object allocations during draw/layout operations (preallocate and reuse instead) [DrawAllocation]\n" +
+ " new String(\"flag me\");\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:112: Warning: Avoid object allocations during draw/layout operations (preallocate and reuse instead) [DrawAllocation]\n" +
+ " Bitmap.createBitmap(100, 100, null);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:113: Warning: Avoid object allocations during draw/layout operations (preallocate and reuse instead) [DrawAllocation]\n" +
+ " android.graphics.Bitmap.createScaledBitmap(null, 100, 100, false);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:114: Warning: Avoid object allocations during draw/layout operations (preallocate and reuse instead) [DrawAllocation]\n" +
+ " BitmapFactory.decodeFile(null);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:116: Warning: Avoid object allocations during draw operations: Use Canvas.getClipBounds(Rect) instead of Canvas.getClipBounds() which allocates a temporary Rect [DrawAllocation]\n" +
+ " canvas.getClipBounds(); // allocates on your behalf\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:140: Warning: Avoid object allocations during draw/layout operations (preallocate and reuse instead) [DrawAllocation]\n" +
+ " new String(\"foo\");\n" +
+ " ~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:70: Warning: Use new SparseArray<String>(...) instead for better performance [UseSparseArrays]\n" +
+ " Map<Integer, String> myMap = new HashMap<Integer, String>();\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:72: Warning: Use new SparseBooleanArray(...) instead for better performance [UseSparseArrays]\n" +
+ " Map<Integer, Boolean> myBoolMap = new HashMap<Integer, Boolean>();\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:74: Warning: Use new SparseIntArray(...) instead for better performance [UseSparseArrays]\n" +
+ " Map<Integer, Integer> myIntMap = new java.util.HashMap<Integer, Integer>();\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:190: Warning: Use new SparseIntArray(...) instead for better performance [UseSparseArrays]\n" +
+ " new SparseArray<Integer>(); // Use SparseIntArray instead\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:192: Warning: Use new SparseBooleanArray(...) instead for better performance [UseSparseArrays]\n" +
+ " new SparseArray<Boolean>(); // Use SparseBooleanArray instead\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:33: Warning: Use Integer.valueOf(5) instead [UseValueOf]\n" +
+ " Integer i = new Integer(5);\n" +
+ " ~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:145: Warning: Use Integer.valueOf(42) instead [UseValueOf]\n" +
+ " Integer i1 = new Integer(42);\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:146: Warning: Use Long.valueOf(42L) instead [UseValueOf]\n" +
+ " Long l1 = new Long(42L);\n" +
+ " ~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:147: Warning: Use Boolean.valueOf(true) instead [UseValueOf]\n" +
+ " Boolean b1 = new Boolean(true);\n" +
+ " ~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:148: Warning: Use Character.valueOf('c') instead [UseValueOf]\n" +
+ " Character c1 = new Character('c');\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:149: Warning: Use Float.valueOf(1.0f) instead [UseValueOf]\n" +
+ " Float f1 = new Float(1.0f);\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/JavaPerformanceTest.java:150: Warning: Use Double.valueOf(1.0) instead [UseValueOf]\n" +
+ " Double d1 = new Double(1.0);\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "0 errors, 21 warnings\n",
+
+ lintProject("src/test/pkg/JavaPerformanceTest.java.txt=>" +
+ "src/test/pkg/JavaPerformanceTest.java"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/LabelForDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/LabelForDetectorTest.java
new file mode 100644
index 0000000..6d69e00
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/LabelForDetectorTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class LabelForDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new LabelForDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/layout/labelfor.xml:54: Warning: No label views point to this text field with an android:labelFor=\"@+id/@+id/editText2\" attribute [LabelFor]\n" +
+ " <EditText\n" +
+ " ^\n" +
+ "res/layout/labelfor.xml:61: Warning: No label views point to this text field with an android:labelFor=\"@+id/@+id/autoCompleteTextView2\" attribute [LabelFor]\n" +
+ " <AutoCompleteTextView\n" +
+ " ^\n" +
+ "res/layout/labelfor.xml:68: Warning: No label views point to this text field with an android:labelFor=\"@+id/@+id/multiAutoCompleteTextView2\" attribute [LabelFor]\n" +
+ " <MultiAutoCompleteTextView\n" +
+ " ^\n" +
+ "0 errors, 3 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk17.xml=>AndroidManifest.xml",
+ "res/layout/labelfor.xml"
+ ));
+ }
+
+ public void testSuppressed() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/minsdk17.xml=>AndroidManifest.xml",
+ "res/layout/labelfor_ignore.xml"
+ ));
+ }
+
+
+ public void testOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/minsdk17.xml=>AndroidManifest.xml",
+ "res/layout/accessibility.xml"
+ ));
+ }
+
+ public void testNotApplicable() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/layout/labelfor.xml"
+ ));
+ }
+}
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/LocaleDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/LocaleDetectorTest.java
new file mode 100644
index 0000000..2ac3c4e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/LocaleDetectorTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class LocaleDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new LocaleDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/LocaleTest.java:11: Warning: Implicitly using the default locale is a common source of bugs: Use toUpperCase(Locale) instead [DefaultLocale]\n" +
+ " System.out.println(\"WRONG\".toUpperCase());\n" +
+ " ~~~~~~~~~~~\n" +
+ "src/test/pkg/LocaleTest.java:16: Warning: Implicitly using the default locale is a common source of bugs: Use toLowerCase(Locale) instead [DefaultLocale]\n" +
+ " System.out.println(\"WRONG\".toLowerCase());\n" +
+ " ~~~~~~~~~~~\n" +
+ "src/test/pkg/LocaleTest.java:20: Warning: Implicitly using the default locale is a common source of bugs: Use String.format(Locale, ...) instead [DefaultLocale]\n" +
+ " String.format(\"WRONG: %f\", 1.0f); // Implies locale\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/LocaleTest.java:21: Warning: Implicitly using the default locale is a common source of bugs: Use String.format(Locale, ...) instead [DefaultLocale]\n" +
+ " String.format(\"WRONG: %1$f\", 1.0f);\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/LocaleTest.java:22: Warning: Implicitly using the default locale is a common source of bugs: Use String.format(Locale, ...) instead [DefaultLocale]\n" +
+ " String.format(\"WRONG: %e\", 1.0f);\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/LocaleTest.java:23: Warning: Implicitly using the default locale is a common source of bugs: Use String.format(Locale, ...) instead [DefaultLocale]\n" +
+ " String.format(\"WRONG: %d\", 1.0f);\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/LocaleTest.java:24: Warning: Implicitly using the default locale is a common source of bugs: Use String.format(Locale, ...) instead [DefaultLocale]\n" +
+ " String.format(\"WRONG: %g\", 1.0f);\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/LocaleTest.java:25: Warning: Implicitly using the default locale is a common source of bugs: Use String.format(Locale, ...) instead [DefaultLocale]\n" +
+ " String.format(\"WRONG: %g\", 1.0f);\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/LocaleTest.java:26: Warning: Implicitly using the default locale is a common source of bugs: Use String.format(Locale, ...) instead [DefaultLocale]\n" +
+ " String.format(\"WRONG: %1$tm %1$te,%1$tY\",\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/LocaleTest.java:32: Warning: To get local formatting use getDateInstance(), getDateTimeInstance(), or getTimeInstance(), or use new SimpleDateFormat(String template, Locale locale) with for example Locale.US for ASCII dates. [SimpleDateFormat]\n" +
+ " new SimpleDateFormat(); // WRONG\n" +
+ " ~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/LocaleTest.java:33: Warning: To get local formatting use getDateInstance(), getDateTimeInstance(), or getTimeInstance(), or use new SimpleDateFormat(String template, Locale locale) with for example Locale.US for ASCII dates. [SimpleDateFormat]\n" +
+ " new SimpleDateFormat(\"yyyy-MM-dd\"); // WRONG\n" +
+ " ~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/LocaleTest.java:34: Warning: To get local formatting use getDateInstance(), getDateTimeInstance(), or getTimeInstance(), or use new SimpleDateFormat(String template, Locale locale) with for example Locale.US for ASCII dates. [SimpleDateFormat]\n" +
+ " new SimpleDateFormat(\"yyyy-MM-dd\", DateFormatSymbols.getInstance()); // WRONG\n" +
+ " ~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 12 warnings\n",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "res/layout/onclick.xml=>res/layout/onclick.xml",
+ "bytecode/LocaleTest.java.txt=>src/test/pkg/LocaleTest.java",
+ "bytecode/LocaleTest.class.data=>bin/classes/test/pkg/LocaleTest.class"
+ ));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ManifestOrderDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ManifestOrderDetectorTest.java
new file mode 100644
index 0000000..ccb9123
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ManifestOrderDetectorTest.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.client.api.LintClient;
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Issue;
+import com.android.tools.lint.detector.api.Project;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+@SuppressWarnings("javadoc")
+public class ManifestOrderDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ManifestOrderDetector();
+ }
+
+ private Set<Issue> mEnabled = new HashSet<Issue>();
+
+ @Override
+ protected TestConfiguration getConfiguration(LintClient client, Project project) {
+ return new TestConfiguration(client, project, null) {
+ @Override
+ public boolean isEnabled(Issue issue) {
+ return super.isEnabled(issue) && mEnabled.contains(issue);
+ }
+ };
+ }
+
+ public void testOrderOk() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.ORDER);
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testBrokenOrder() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.ORDER);
+ assertEquals(
+ "AndroidManifest.xml:16: Warning: <uses-sdk> tag appears after <application> tag [ManifestOrder]\n" +
+ " <uses-sdk android:minSdkVersion=\"Froyo\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "broken-manifest.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testMissingUsesSdk() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.USES_SDK);
+ assertEquals(
+ "AndroidManifest.xml: Warning: Manifest should specify a minimum API level with <uses-sdk android:minSdkVersion=\"?\" />; if it really supports all versions of Android set it to 1. [UsesMinSdkAttributes]\n" +
+ "0 errors, 1 warnings\n",
+ lintProject(
+ "missingusessdk.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testMissingMinSdk() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.USES_SDK);
+ assertEquals(
+ "AndroidManifest.xml:7: Warning: <uses-sdk> tag should specify a minimum API level with android:minSdkVersion=\"?\" [UsesMinSdkAttributes]\n" +
+ " <uses-sdk android:targetSdkVersion=\"10\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject(
+ "missingmin.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testMissingTargetSdk() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.USES_SDK);
+ assertEquals(
+ "AndroidManifest.xml:7: Warning: <uses-sdk> tag should specify a target API level (the highest verified version; when running on later versions, compatibility behaviors may be enabled) with android:targetSdkVersion=\"?\" [UsesMinSdkAttributes]\n" +
+ " <uses-sdk android:minSdkVersion=\"10\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n",
+ lintProject(
+ "missingtarget.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testOldTargetSdk() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.TARGET_NEWER);
+ assertEquals(
+ "AndroidManifest.xml:7: Warning: Not targeting the latest versions of Android; compatibility modes apply. Consider testing and updating this version. Consult the android.os.Build.VERSION_CODES javadoc for details. [OldTargetApi]\n" +
+ " <uses-sdk android:minSdkVersion=\"10\" android:targetSdkVersion=\"14\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n",
+ lintProject(
+ "oldtarget.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testMultipleSdk() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.MULTIPLE_USES_SDK);
+ assertEquals(
+ "AndroidManifest.xml:8: Error: There should only be a single <uses-sdk> element in the manifest: merge these together [MultipleUsesSdk]\n" +
+ " <uses-sdk android:targetSdkVersion=\"14\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " AndroidManifest.xml:7: Also appears here\n" +
+ " AndroidManifest.xml:9: Also appears here\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject(
+ "multiplesdk.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testWrongLocation() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.WRONG_PARENT);
+ assertEquals(
+ "AndroidManifest.xml:8: Error: The <uses-sdk> element must be a direct child of the <manifest> root element [WrongManifestParent]\n" +
+ " <uses-sdk android:minSdkVersion=\"Froyo\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:9: Error: The <uses-permission> element must be a direct child of the <manifest> root element [WrongManifestParent]\n" +
+ " <uses-permission />\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:10: Error: The <permission> element must be a direct child of the <manifest> root element [WrongManifestParent]\n" +
+ " <permission />\n" +
+ " ~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:11: Error: The <permission-tree> element must be a direct child of the <manifest> root element [WrongManifestParent]\n" +
+ " <permission-tree />\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:12: Error: The <permission-group> element must be a direct child of the <manifest> root element [WrongManifestParent]\n" +
+ " <permission-group />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:14: Error: The <uses-sdk> element must be a direct child of the <manifest> root element [WrongManifestParent]\n" +
+ " <uses-sdk />\n" +
+ " ~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:15: Error: The <uses-configuration> element must be a direct child of the <manifest> root element [WrongManifestParent]\n" +
+ " <uses-configuration />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:16: Error: The <uses-feature> element must be a direct child of the <manifest> root element [WrongManifestParent]\n" +
+ " <uses-feature />\n" +
+ " ~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:17: Error: The <supports-screens> element must be a direct child of the <manifest> root element [WrongManifestParent]\n" +
+ " <supports-screens />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:18: Error: The <compatible-screens> element must be a direct child of the <manifest> root element [WrongManifestParent]\n" +
+ " <compatible-screens />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:19: Error: The <supports-gl-texture> element must be a direct child of the <manifest> root element [WrongManifestParent]\n" +
+ " <supports-gl-texture />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:24: Error: The <uses-library> element must be a direct child of the <application> element [WrongManifestParent]\n" +
+ " <uses-library />\n" +
+ " ~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:25: Error: The <activity> element must be a direct child of the <application> element [WrongManifestParent]\n" +
+ " <activity android:name=\".HelloWorld\"\n" +
+ " ^\n" +
+ "13 errors, 0 warnings\n" +
+ "",
+
+ lintProject("broken-manifest2.xml=>AndroidManifest.xml"));
+ }
+
+ public void testDuplicateActivity() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.DUPLICATE_ACTIVITY);
+ assertEquals(
+ "AndroidManifest.xml:16: Error: Duplicate registration for activity com.example.helloworld.HelloWorld [DuplicateActivity]\n" +
+ " <activity android:name=\"com.example.helloworld.HelloWorld\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n" +
+ "",
+
+ lintProject(
+ "duplicate-manifest.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testIgnoreDuplicateActivity() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.DUPLICATE_ACTIVITY);
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "duplicate-manifest-ignore.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testAllowBackup() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.ALLOW_BACKUP);
+ assertEquals(
+ "AndroidManifest.xml:9: Warning: Should explicitly set android:allowBackup to " +
+ "true or false (it's true by default, and that can have some security " +
+ "implications for the application's data) [AllowBackup]\n" +
+ " <application\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n",
+ lintProject(
+ "AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testAllowBackupOk() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.ALLOW_BACKUP);
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "allowbackup.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testAllowIgnore() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.ALLOW_BACKUP);
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "allowbackup_ignore.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testDuplicatePermissions() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.UNIQUE_PERMISSION);
+ assertEquals(
+ "AndroidManifest.xml:12: Error: Permission name SEND_SMS is not unique (appears in both foo.permission.SEND_SMS and bar.permission.SEND_SMS) [UniquePermission]\n" +
+ " <permission android:name=\"bar.permission.SEND_SMS\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " AndroidManifest.xml:9: Previous permission here\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject(
+ "duplicate_permissions1.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testDuplicatePermissionsMultiProject() throws Exception {
+ mEnabled = Collections.singleton(ManifestOrderDetector.UNIQUE_PERMISSION);
+
+ File master = getProjectDir("MasterProject",
+ // Master project
+ "duplicate_permissions2.xml=>AndroidManifest.xml",
+ "multiproject/main-merge.properties=>project.properties",
+ "multiproject/MainCode.java.txt=>src/foo/main/MainCode.java"
+ );
+ File library = getProjectDir("LibraryProject",
+ // Library project
+ "duplicate_permissions3.xml=>AndroidManifest.xml",
+ "multiproject/library.properties=>project.properties",
+ "multiproject/LibraryCode.java.txt=>src/foo/library/LibraryCode.java",
+ "multiproject/strings.xml=>res/values/strings.xml"
+ );
+ assertEquals(
+ "LibraryProject/AndroidManifest.xml:9: Error: Permission name SEND_SMS is not unique (appears in both foo.permission.SEND_SMS and bar.permission.SEND_SMS) [UniquePermission]\n" +
+ " <permission android:name=\"bar.permission.SEND_SMS\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n",
+
+ checkLint(Arrays.asList(master, library)));
+ }
+
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/MathDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/MathDetectorTest.java
new file mode 100644
index 0000000..da12bda
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/MathDetectorTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class MathDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new MathDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/bytecode/MathTest.java:11: Warning: Use java.lang.Math#cos instead of android.util.FloatMath#cos() since it is faster as of API 8 [FloatMath]\n" +
+ " floatResult = FloatMath.cos(x);\n" +
+ " ~~~\n" +
+ "src/test/bytecode/MathTest.java:12: Warning: Use java.lang.Math#sin instead of android.util.FloatMath#sin() since it is faster as of API 8 [FloatMath]\n" +
+ " floatResult = FloatMath.sin((float) y);\n" +
+ " ~~~\n" +
+ "src/test/bytecode/MathTest.java:13: Warning: Use java.lang.Math#ceil instead of android.util.FloatMath#ceil() since it is faster as of API 8 [FloatMath]\n" +
+ " floatResult = android.util.FloatMath.ceil((float) y);\n" +
+ " ~~~~\n" +
+ "src/test/bytecode/MathTest.java:14: Warning: Use java.lang.Math#floor instead of android.util.FloatMath#floor() since it is faster as of API 8 [FloatMath]\n" +
+ " System.out.println(FloatMath.floor(x));\n" +
+ " ~~~~~\n" +
+ "src/test/bytecode/MathTest.java:15: Warning: Use java.lang.Math#sqrt instead of android.util.FloatMath#sqrt() since it is faster as of API 8 [FloatMath]\n" +
+ " System.out.println(FloatMath.sqrt(z));\n" +
+ " ~~~~\n" +
+ "0 errors, 5 warnings\n",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "bytecode/MathTest.java.txt=>src/test/bytecode/MathTest.java",
+ "bytecode/MathTest.class.data=>bin/classes/test/bytecode/MathTest.class"
+ ));
+ }
+
+ public void testNoWarningsPreFroyo() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "apicheck/minsdk2.xml=>AndroidManifest.xml",
+ "bytecode/MathTest.java.txt=>src/test/bytecode/MathTest.java",
+ "bytecode/MathTest.class.data=>bin/classes/test/bytecode/MathTest.class"
+ ));
+ }
+
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/MergeRootFrameLayoutDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/MergeRootFrameLayoutDetectorTest.java
new file mode 100644
index 0000000..22a001f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/MergeRootFrameLayoutDetectorTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class MergeRootFrameLayoutDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new MergeRootFrameLayoutDetector();
+ }
+
+
+ public void testMergeRefFromJava() throws Exception {
+ assertEquals(
+ "res/layout/simple.xml:3: Warning: This <FrameLayout> can be replaced with a <merge> tag [MergeRootFrame]\n" +
+ "<FrameLayout\n" +
+ "^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject(
+ "res/layout/simple.xml",
+ "src/test/pkg/ImportFrameActivity.java.txt=>src/test/pkg/ImportFrameActivity.java"
+ ));
+ }
+
+ public void testMergeRefFromInclude() throws Exception {
+ assertEquals(
+ "res/layout/simple.xml:3: Warning: This <FrameLayout> can be replaced with a <merge> tag [MergeRootFrame]\n" +
+ "<FrameLayout\n" +
+ "^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject(
+ "res/layout/simple.xml",
+ "res/layout/simpleinclude.xml"
+ ));
+ }
+
+ public void testMergeRefFromIncludeSuppressed() throws Exception {
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "res/layout/simple_ignore.xml=>res/layout/simple.xml",
+ "res/layout/simpleinclude.xml"
+ ));
+ }
+
+ public void testNotIncluded() throws Exception {
+ assertEquals(
+ "No warnings.",
+ lintProject("res/layout/simple.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/MissingClassDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/MissingClassDetectorTest.java
new file mode 100644
index 0000000..4edf345
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/MissingClassDetectorTest.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Scope;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+@SuppressWarnings("javadoc")
+public class MissingClassDetectorTest extends AbstractCheckTest {
+ private EnumSet<Scope> mScopes;
+
+ @Override
+ protected Detector getDetector() {
+ return new MissingClassDetector();
+ }
+
+ @Override
+ protected EnumSet<Scope> getLintScope(List<File> file) {
+ return mScopes;
+ }
+
+ public void test() throws Exception {
+ mScopes = null;
+ assertEquals(
+ "AndroidManifest.xml:13: Error: Class referenced in the manifest, test.pkg.TestProvider, was not found in the project or the libraries [MissingRegistered]\n" +
+ " <activity android:name=\".TestProvider\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:14: Error: Class referenced in the manifest, test.pkg.TestProvider2, was not found in the project or the libraries [MissingRegistered]\n" +
+ " <service android:name=\"test.pkg.TestProvider2\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:15: Error: Class referenced in the manifest, test.pkg.TestService, was not found in the project or the libraries [MissingRegistered]\n" +
+ " <provider android:name=\".TestService\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:16: Error: Class referenced in the manifest, test.pkg.OnClickActivity, was not found in the project or the libraries [MissingRegistered]\n" +
+ " <receiver android:name=\"OnClickActivity\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:17: Error: Class referenced in the manifest, test.pkg.TestReceiver, was not found in the project or the libraries [MissingRegistered]\n" +
+ " <service android:name=\"TestReceiver\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "5 errors, 0 warnings\n",
+
+ lintProject(
+ "bytecode/AndroidManifestWrongRegs.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest.class.data=>bin/classes/foo/bar/ApiCallTest.class",
+ "bytecode/.classpath=>.classpath"
+ ));
+ }
+
+ public void testIncrementalInManifest() throws Exception {
+ mScopes = Scope.MANIFEST_SCOPE;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/AndroidManifestWrongRegs.xml=>AndroidManifest.xml",
+ "bytecode/.classpath=>.classpath"
+ ));
+ }
+
+ public void testNoWarningBeforeBuild() throws Exception {
+ mScopes = null;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/AndroidManifestWrongRegs.xml=>AndroidManifest.xml",
+ "bytecode/.classpath=>.classpath"
+ ));
+ }
+
+ public void testOkClasses() throws Exception {
+ mScopes = null;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/AndroidManifestWrongRegs.xml=>AndroidManifest.xml",
+ "bytecode/.classpath=>.classpath",
+ "bytecode/OnClickActivity.java.txt=>src/test/pkg/OnClickActivity.java",
+ "bytecode/OnClickActivity.class.data=>bin/classes/test/pkg/OnClickActivity.class",
+ "bytecode/TestService.java.txt=>src/test/pkg/TestService.java",
+ "bytecode/TestService.class.data=>bin/classes/test/pkg/TestService.class",
+ "bytecode/TestProvider.java.txt=>src/test/pkg/TestProvider.java",
+ "bytecode/TestProvider.class.data=>bin/classes/test/pkg/TestProvider.class",
+ "bytecode/TestProvider2.java.txt=>src/test/pkg/TestProvider2.java",
+ "bytecode/TestProvider2.class.data=>bin/classes/test/pkg/TestProvider2.class",
+ "bytecode/TestReceiver.java.txt=>src/test/pkg/TestReceiver.java",
+ "bytecode/TestReceiver.class.data=>bin/classes/test/pkg/TestReceiver.class"
+ ));
+ }
+
+ public void testOkLibraries() throws Exception {
+ mScopes = null;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/AndroidManifestWrongRegs.xml=>AndroidManifest.xml",
+ "bytecode/.classpath=>.classpath",
+ "bytecode/classes.jar=>libs/classes.jar"
+ ));
+ }
+
+ public void testLibraryProjects() throws Exception {
+ mScopes = null;
+ File master = getProjectDir("MasterProject",
+ // Master project
+ "bytecode/AndroidManifestWrongRegs.xml=>AndroidManifest.xml",
+ "multiproject/main.properties=>project.properties",
+ "bytecode/.classpath=>.classpath"
+ );
+ File library = getProjectDir("LibraryProject",
+ // Library project
+ "multiproject/library-manifest.xml=>AndroidManifest.xml",
+ "multiproject/library.properties=>project.properties",
+ "bytecode/OnClickActivity.java.txt=>src/test/pkg/OnClickActivity.java",
+ "bytecode/OnClickActivity.class.data=>bin/classes/test/pkg/OnClickActivity.class",
+ "bytecode/TestService.java.txt=>src/test/pkg/TestService.java",
+ "bytecode/TestService.class.data=>bin/classes/test/pkg/TestService.class",
+ "bytecode/TestProvider.java.txt=>src/test/pkg/TestProvider.java",
+ "bytecode/TestProvider.class.data=>bin/classes/test/pkg/TestProvider.class",
+ "bytecode/TestProvider2.java.txt=>src/test/pkg/TestProvider2.java",
+ "bytecode/TestProvider2.class.data=>bin/classes/test/pkg/TestProvider2.class"
+ // Missing TestReceiver: Test should complain about just that class
+ );
+ assertEquals(
+ "MasterProject/AndroidManifest.xml:17: Error: Class referenced in the manifest, test.pkg.TestReceiver, was not found in the project or the libraries [MissingRegistered]\n" +
+ " <service android:name=\"TestReceiver\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n",
+
+ checkLint(Arrays.asList(master, library)));
+ }
+
+ public void testInnerClassStatic() throws Exception {
+ mScopes = null;
+ assertEquals(
+ "src/test/pkg/Foo.java:8: Warning: This inner class should be static (test.pkg.Foo.Baz) [Instantiatable]\n" +
+ " public class Baz extends Activity {\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n",
+
+ lintProject(
+ "registration/AndroidManifest.xml=>AndroidManifest.xml",
+ "bytecode/.classpath=>.classpath",
+ "registration/Foo.java.txt=>src/test/pkg/Foo.java",
+ "registration/Foo.class.data=>bin/classes/test/pkg/Foo.class",
+ "registration/Foo$Bar.class.data=>bin/classes/test/pkg/Foo$Bar.class",
+ "registration/Foo$Baz.class.data=>bin/classes/test/pkg/Foo$Baz.class"
+ ));
+ }
+
+ public void testInnerClassPublic() throws Exception {
+ mScopes = null;
+ assertEquals(
+ "src/test/pkg/Foo/Bar.java:6: Warning: The default constructor must be public [Instantiatable]\n" +
+ " private Bar() {\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n",
+
+ lintProject(
+ "registration/AndroidManifestInner.xml=>AndroidManifest.xml",
+ "bytecode/.classpath=>.classpath",
+ "registration/Bar.java.txt=>src/test/pkg/Foo/Bar.java",
+ "registration/Bar.class.data=>bin/classes/test/pkg/Foo/Bar.class"
+ ));
+ }
+
+ public void testInnerClass() throws Exception {
+ mScopes = null;
+ assertEquals(
+ "AndroidManifest.xml:14: Error: Class referenced in the manifest, test.pkg.Foo.Bar, was not found in the project or the libraries [MissingRegistered]\n" +
+ " <activity\n" +
+ " ^\n" +
+ "AndroidManifest.xml:23: Error: Class referenced in the manifest, test.pkg.Foo.Baz, was not found in the project or the libraries [MissingRegistered]\n" +
+ " <activity\n" +
+ " ^\n" +
+ "2 errors, 0 warnings\n",
+
+ lintProject(
+ "registration/AndroidManifest.xml=>AndroidManifest.xml",
+ "bytecode/.classpath=>.classpath",
+ "apicheck/ApiCallTest.class.data=>bin/classes/foo/bar/ApiCallTest.class",
+ "registration/Foo.java.txt=>src/test/pkg/Foo.java"
+ ));
+ }
+
+ public void testInnerClass2() throws Exception {
+ mScopes = null;
+ assertEquals(
+ "AndroidManifest.xml:14: Error: Class referenced in the manifest, test.pkg.Foo.Bar, was not found in the project or the libraries [MissingRegistered]\n" +
+ " <activity\n" +
+ " ^\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject(
+ "registration/AndroidManifestInner.xml=>AndroidManifest.xml",
+ "bytecode/.classpath=>.classpath",
+ "apicheck/ApiCallTest.class.data=>bin/classes/foo/bar/ApiCallTest.class",
+ "registration/Bar.java.txt=>src/test/pkg/Foo/Bar.java"
+ ));
+ }
+
+ public void testWrongSeparator1() throws Exception {
+ mScopes = null;
+ assertEquals(
+ "AndroidManifest.xml:14: Error: Class referenced in the manifest, test.pkg.Foo.Bar, was not found in the project or the libraries [MissingRegistered]\n" +
+ " <activity\n" +
+ " ^\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject(
+ "registration/AndroidManifestWrong.xml=>AndroidManifest.xml",
+ "bytecode/.classpath=>.classpath",
+ "apicheck/ApiCallTest.class.data=>bin/classes/foo/bar/ApiCallTest.class",
+ "registration/Bar.java.txt=>src/test/pkg/Foo/Bar.java"
+ ));
+ }
+
+ public void testWrongSeparator2() throws Exception {
+ mScopes = null;
+ assertEquals(
+ "AndroidManifest.xml:14: Error: Class referenced in the manifest, test.pkg.Foo.Bar, was not found in the project or the libraries [MissingRegistered]\n" +
+ " <activity\n" +
+ " ^\n" +
+ "AndroidManifest.xml:15: Warning: Use '$' instead of '.' for inner classes (or use only lowercase letters in package names) [InnerclassSeparator]\n" +
+ " android:name=\".Foo.Bar\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 1 warnings\n",
+
+ lintProject(
+ "registration/AndroidManifestWrong2.xml=>AndroidManifest.xml",
+ "bytecode/.classpath=>.classpath",
+ "apicheck/ApiCallTest.class.data=>bin/classes/foo/bar/ApiCallTest.class",
+ "registration/Bar.java.txt=>src/test/pkg/Foo/Bar.java"
+ ));
+ }
+
+ public void testNoClassesWithLibraries() throws Exception {
+ mScopes = null;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/AndroidManifestWrongRegs.xml=>AndroidManifest.xml",
+ "bytecode/.classpath=>.classpath",
+ "bytecode/GetterTest.jar.data=>libs/foo.jar"
+ ));
+ }
+
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/MissingIdDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/MissingIdDetectorTest.java
new file mode 100644
index 0000000..b72d8c8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/MissingIdDetectorTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class MissingIdDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new MissingIdDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/layout/fragment.xml:7: Warning: This <fragment> tag should specify an id or a tag to preserve state across activity restarts [MissingId]\n" +
+ " <fragment\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n",
+
+ lintProject("res/layout/fragment.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/NamespaceDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/NamespaceDetectorTest.java
new file mode 100644
index 0000000..91aedb2
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/NamespaceDetectorTest.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class NamespaceDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new NamespaceDetector();
+ }
+
+ public void testCustom() throws Exception {
+ assertEquals(
+ "res/layout/customview.xml:5: Error: When using a custom namespace attribute in a library project, use the namespace \"http://schemas.android.com/apk/res-auto\" instead. [LibraryCustomView]\n" +
+ " xmlns:foo=\"http://schemas.android.com/apk/res/foo\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject(
+ "multiproject/library-manifest.xml=>AndroidManifest.xml",
+ "multiproject/library.properties=>project.properties",
+ "res/layout/customview.xml"
+ ));
+ }
+
+ public void testCustomOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "multiproject/library-manifest.xml=>AndroidManifest.xml",
+
+ // Use a standard project properties instead: no warning since it's
+ // not a library project:
+ //"multiproject/library.properties=>project.properties",
+
+ "res/layout/customview.xml"
+ ));
+ }
+
+ public void testCustomOk2() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "multiproject/library-manifest.xml=>AndroidManifest.xml",
+ "multiproject/library.properties=>project.properties",
+ // This project already uses the res-auto package
+ "res/layout/customview2.xml"
+ ));
+ }
+
+ public void testTypo() throws Exception {
+ assertEquals(
+ "res/layout/wrong_namespace.xml:2: Warning: Unexpected namespace URI bound to the \"android\" prefix, was http://schemas.android.com/apk/res/andriod, expected http://schemas.android.com/apk/res/android [NamespaceTypo]\n" +
+ "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/andriod\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject("res/layout/wrong_namespace.xml"));
+ }
+
+ public void testTypo2() throws Exception {
+ assertEquals(
+ "res/layout/wrong_namespace2.xml:2: Warning: URI is case sensitive: was \"http://schemas.android.com/apk/res/Android\", expected \"http://schemas.android.com/apk/res/android\" [NamespaceTypo]\n" +
+ "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/Android\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject("res/layout/wrong_namespace2.xml"));
+ }
+
+ public void testTypo3() throws Exception {
+ assertEquals(
+ "res/layout/wrong_namespace3.xml:2: Warning: Unexpected namespace URI bound to the \"android\" prefix, was http://schemas.android.com/apk/res/androi, expected http://schemas.android.com/apk/res/android [NamespaceTypo]\n" +
+ "<LinearLayout xmlns:a=\"http://schemas.android.com/apk/res/androi\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject("res/layout/wrong_namespace3.xml"));
+ }
+
+ public void testTypo4() throws Exception {
+ assertEquals(
+ "res/layout/wrong_namespace5.xml:2: Warning: Suspicious namespace: should start with http:// [NamespaceTypo]\n" +
+ " xmlns:noturi=\"tp://schems.android.com/apk/res/com.my.package\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrong_namespace5.xml:3: Warning: Possible typo in URL: was \"http://schems.android.com/apk/res/com.my.package\", should probably be \"http://schemas.android.com/apk/res/com.my.package\" [NamespaceTypo]\n" +
+ " xmlns:typo1=\"http://schems.android.com/apk/res/com.my.package\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrong_namespace5.xml:4: Warning: Possible typo in URL: was \"http://schems.android.comm/apk/res/com.my.package\", should probably be \"http://schemas.android.com/apk/res/com.my.package\" [NamespaceTypo]\n" +
+ " xmlns:typo2=\"http://schems.android.comm/apk/res/com.my.package\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 3 warnings\n",
+
+ lintProject("res/layout/wrong_namespace5.xml"));
+ }
+
+ public void testTypoOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject("res/layout/wrong_namespace4.xml"));
+ }
+
+ public void testUnused() throws Exception {
+ assertEquals(
+ "res/layout/unused_namespace.xml:3: Warning: Unused namespace unused1 [UnusedNamespace]\n" +
+ " xmlns:unused1=\"http://schemas.android.com/apk/res/unused1\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/unused_namespace.xml:4: Warning: Unused namespace unused2 [UnusedNamespace]\n" +
+ " xmlns:unused2=\"http://schemas.android.com/apk/res/unused1\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 2 warnings\n" +
+ "",
+
+ lintProject("res/layout/unused_namespace.xml"));
+ }
+
+ public void testUnusedOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject("res/layout/layout1.xml"));
+ }
+
+ public void testLayoutAttributesOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles("res/layout/namespace3.xml"));
+ }
+
+ public void testLayoutAttributesOk2() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles("res/layout/namespace4.xml"));
+ }
+
+ public void testLayoutAttributes() throws Exception {
+ assertEquals(
+ "res/layout/namespace3.xml:2: Error: When using a custom namespace attribute in a library project, use the namespace \"http://schemas.android.com/apk/res-auto\" instead. [LibraryCustomView]\n" +
+ " xmlns:app=\"http://schemas.android.com/apk/res/com.example.apicalltest\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n",
+
+ lintFiles("res/layout/namespace3.xml",
+ "multiproject/library-manifest.xml=>AndroidManifest.xml",
+ "multiproject/library.properties=>project.properties"));
+ }
+
+ public void testLayoutAttributes2() throws Exception {
+ assertEquals(
+ "res/layout/namespace4.xml:3: Error: When using a custom namespace attribute in a library project, use the namespace \"http://schemas.android.com/apk/res-auto\" instead. [LibraryCustomView]\n" +
+ " xmlns:app=\"http://schemas.android.com/apk/res/com.example.apicalltest\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n",
+
+ lintFiles("res/layout/namespace4.xml",
+ "multiproject/library-manifest.xml=>AndroidManifest.xml",
+ "multiproject/library.properties=>project.properties"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/NestedScrollingWidgetDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/NestedScrollingWidgetDetectorTest.java
new file mode 100644
index 0000000..55da17e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/NestedScrollingWidgetDetectorTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class NestedScrollingWidgetDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new NestedScrollingWidgetDetector();
+ }
+
+ public void testNested() throws Exception {
+ assertEquals(
+ "res/layout/scrolling.xml:13: Warning: The vertically scrolling ScrollView should not contain another vertically scrolling widget (ListView) [NestedScrolling]\n" +
+ " <ListView\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n",
+
+ lintFiles("res/layout/scrolling.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/NonInternationalizedSmsDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/NonInternationalizedSmsDetectorTest.java
new file mode 100644
index 0000000..46e494e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/NonInternationalizedSmsDetectorTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class NonInternationalizedSmsDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new NonInternationalizedSmsDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/NonInternationalizedSmsDetectorTest.java:18: Warning: To make sure the SMS can be sent by all users, please start the SMS numberwith a + and a country code or restrict the code invocation to people in the country you are targeting. [UnlocalizedSms]\n" +
+ " sms.sendMultipartTextMessage(\"001234567890\", null, null, null, null);\n" +
+ " ~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject("src/test/pkg/NonInternationalizedSmsDetectorTest.java.txt=>src/test/pkg/NonInternationalizedSmsDetectorTest.java"));
+ }
+} \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ObsoleteLayoutParamsDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ObsoleteLayoutParamsDetectorTest.java
new file mode 100644
index 0000000..87211a2
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ObsoleteLayoutParamsDetectorTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class ObsoleteLayoutParamsDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ObsoleteLayoutParamsDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/layout/wrongparams.xml:11: Warning: Invalid layout param in a FrameLayout: layout_weight [ObsoleteLayoutParam]\n" +
+ " android:layout_weight=\"1\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrongparams.xml:23: Warning: Invalid layout param in a LinearLayout: layout_alignParentLeft [ObsoleteLayoutParam]\n" +
+ " android:layout_alignParentLeft=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrongparams.xml:24: Warning: Invalid layout param in a LinearLayout: layout_alignParentTop [ObsoleteLayoutParam]\n" +
+ " android:layout_alignParentTop=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrongparams.xml:33: Warning: Invalid layout param in a LinearLayout: layout_alignBottom [ObsoleteLayoutParam]\n" +
+ " android:layout_alignBottom=\"@+id/button1\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrongparams.xml:34: Warning: Invalid layout param in a LinearLayout: layout_toRightOf [ObsoleteLayoutParam]\n" +
+ " android:layout_toRightOf=\"@+id/button1\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrongparams.xml:42: Warning: Invalid layout param in a LinearLayout: layout_alignLeft [ObsoleteLayoutParam]\n" +
+ " android:layout_alignLeft=\"@+id/button1\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrongparams.xml:43: Warning: Invalid layout param in a LinearLayout: layout_below [ObsoleteLayoutParam]\n" +
+ " android:layout_below=\"@+id/button1\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 7 warnings\n" +
+ "",
+
+ lintProject("res/layout/wrongparams.xml"));
+ }
+
+ public void test2() throws Exception {
+ // Test <merge> and custom view handling
+
+ assertEquals(
+ "No warnings.",
+
+ lintProject("res/layout/wrongparams2.xml"));
+ }
+
+ public void test3() throws Exception {
+ // Test includes across files (wrong layout param on root element)
+ assertEquals(
+ "res/layout/wrongparams3.xml:5: Warning: Invalid layout param 'layout_alignParentTop' (included from within a LinearLayout in layout/wrongparams4.xml) [ObsoleteLayoutParam]\n" +
+ " android:layout_alignParentTop=\"true\" >\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject("res/layout/wrongparams4.xml", "res/layout/wrongparams3.xml"));
+ }
+
+ public void test4() throws Exception {
+ // Test includes with a <merge> (wrong layout param on child of root merge element)
+ assertEquals(
+ "res/layout/wrongparams5.xml:8: Warning: Invalid layout param 'layout_alignParentTop' (included from within a LinearLayout in layout/wrongparams6.xml) [ObsoleteLayoutParam]\n" +
+ " android:layout_alignParentTop=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/wrongparams5.xml:15: Warning: Invalid layout param 'layout_alignParentLeft' (included from within a LinearLayout in layout/wrongparams6.xml) [ObsoleteLayoutParam]\n" +
+ " android:layout_alignParentLeft=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 2 warnings\n" +
+ "",
+
+ lintProject("res/layout/wrongparams5.xml", "res/layout/wrongparams6.xml"));
+ }
+
+ public void testIgnore() throws Exception {
+ assertEquals(
+ // Ignoring all but one of the warnings
+ "res/layout/wrongparams.xml:12: Warning: Invalid layout param in a FrameLayout: layout_weight [ObsoleteLayoutParam]\n" +
+ " android:layout_weight=\"1\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject("res/layout/wrongparams_ignore.xml=>res/layout/wrongparams.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/OnClickDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/OnClickDetectorTest.java
new file mode 100644
index 0000000..e4d8bb5
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/OnClickDetectorTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class OnClickDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new OnClickDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/OnClickActivity.java:27: Error: On click handler wrong5(View) must be public [OnClick]\n" +
+ " void wrong5(View view) {\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/OnClickActivity.java:31: Error: On click handler wrong6(View) should not be static [OnClick]\n" +
+ " public static void wrong6(View view) {\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/OnClickActivity.java:45: Error: On click handler wrong7(View) must be public [OnClick]\n" +
+ " void wrong7(View view) {\n" +
+ " ~~~~~~\n" +
+ "res/layout/onclick.xml:10: Error: Corresponding method handler 'public void nonexistent(android.view.View)' not found [OnClick]\n" +
+ " android:onClick=\"nonexistent\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/onclick.xml:16: Error: Corresponding method handler 'public void wrong1(android.view.View)' not found [OnClick]\n" +
+ " android:onClick=\"wrong1\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/onclick.xml:22: Error: Corresponding method handler 'public void wrong2(android.view.View)' not found [OnClick]\n" +
+ " android:onClick=\"wrong2\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/onclick.xml:28: Error: Corresponding method handler 'public void wrong3(android.view.View)' not found [OnClick]\n" +
+ " android:onClick=\"wrong3\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/onclick.xml:34: Error: Corresponding method handler 'public void wrong4(android.view.View)' not found [OnClick]\n" +
+ " android:onClick=\"wrong4\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/onclick.xml:58: Error: Corresponding method handler 'public void simple_typo(android.view.View)' not found (did you mean void test.pkg.OnClickActivity#simple_tyop(android.view.View) ?) [OnClick]\n" +
+ " android:onClick=\"simple_typo\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "9 errors, 0 warnings\n",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "res/layout/onclick.xml=>res/layout/onclick.xml",
+ "bytecode/OnClickActivity.java.txt=>src/test/pkg/OnClickActivity.java",
+ "bytecode/OnClickActivity.class.data=>bin/classes/test/pkg/OnClickActivity.class"
+ ));
+ }
+
+ public void testOk() throws Exception {
+ // No onClick attributes
+ assertEquals(
+ "No warnings.",
+
+ lintProject("res/layout/accessibility.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/OverdrawDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/OverdrawDetectorTest.java
new file mode 100644
index 0000000..7da4004
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/OverdrawDetectorTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class OverdrawDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new OverdrawDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/layout/main.xml:5: Warning: Possible overdraw: Root element paints background @drawable/ic_launcher with a theme that also paints a background (inferred theme is @style/MyTheme_First) [Overdraw]\n" +
+ " android:background=\"@drawable/ic_launcher\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/second.xml:5: Warning: Possible overdraw: Root element paints background @drawable/ic_launcher with a theme that also paints a background (inferred theme is @style/MyTheme) [Overdraw]\n" +
+ " android:background=\"@drawable/ic_launcher\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/sixth.xml:4: Warning: Possible overdraw: Root element paints background @drawable/custombg with a theme that also paints a background (inferred theme is @style/MyTheme) [Overdraw]\n" +
+ " android:background=\"@drawable/custombg\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/third.xml:5: Warning: Possible overdraw: Root element paints background @drawable/ic_launcher with a theme that also paints a background (inferred theme is @style/MyTheme_Third) [Overdraw]\n" +
+ " android:background=\"@drawable/ic_launcher\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 4 warnings\n" +
+ "",
+
+ lintProject(
+ "overdraw/.classpath=>.classpath",
+ "overdraw/.project=>.project",
+ "overdraw/AndroidManifest.xml=>AndroidManifest.xml",
+ "overdraw/project.properties=>project.properties",
+ "overdraw/res/drawable/custombg.xml=>res/drawable/custombg.xml",
+ "overdraw/res/drawable/custombg2.xml=>res/drawable/custombg2.xml",
+ "overdraw/res/drawable-hdpi/ic_launcher.png=>res/drawable-hdpi/ic_launcher.png",
+ "overdraw/res/drawable-ldpi/ic_launcher.png=>res/drawable-ldpi/ic_launcher.png",
+ "overdraw/res/drawable-mdpi/ic_launcher.png=>res/drawable-mdpi/ic_launcher.png",
+ "overdraw/res/layout/sixth.xml=>res/layout/sixth.xml",
+ "overdraw/res/layout/fifth.xml=>res/layout/fifth.xml",
+ "overdraw/res/layout/fourth.xml=>res/layout/fourth.xml",
+ "overdraw/res/layout/main.xml=>res/layout/main.xml",
+ "overdraw/res/layout/second.xml=>res/layout/second.xml",
+ "overdraw/res/layout/third.xml=>res/layout/third.xml",
+ "overdraw/res/values/strings.xml=>res/values/strings.xml",
+ "overdraw/res/values/styles.xml=>res/values/styles.xml",
+
+ // Java files must be renamed in source tree
+ "overdraw/gen/test/pkg/BuildConfig.java.txt=>gen/test/pkg/BuildConfig.java",
+ "overdraw/gen/test/pkg/R.java.txt=>gen/test/pkg/R.java",
+ "overdraw/src/test/pkg/FourthActivity.java.txt=>src/test/pkg/FourthActivity.java",
+ "overdraw/src/test/pkg/OverdrawActivity.java.txt=>src/test/pkg/OverdrawActivity.java",
+ "overdraw/src/test/pkg/SecondActivity.java.txt=>src/test/pkg/SecondActivity.java",
+ "overdraw/src/test/pkg/ThirdActivity.java.txt=>src/test/pkg/ThirdActivity.java"
+ ));
+ }
+
+ public void testSuppressed() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "overdraw/.classpath=>.classpath",
+ "overdraw/.project=>.project",
+ "overdraw/AndroidManifest.xml=>AndroidManifest.xml",
+ "overdraw/project.properties=>project.properties",
+ "overdraw/res/drawable/custombg.xml=>res/drawable/custombg.xml",
+ "overdraw/res/drawable/custombg2.xml=>res/drawable/custombg2.xml",
+ "overdraw/res/drawable-hdpi/ic_launcher.png=>res/drawable-hdpi/ic_launcher.png",
+ "overdraw/res/drawable-ldpi/ic_launcher.png=>res/drawable-ldpi/ic_launcher.png",
+ "overdraw/res/drawable-mdpi/ic_launcher.png=>res/drawable-mdpi/ic_launcher.png",
+ "overdraw/res/layout/main_ignore.xml=>res/layout/main.xml",
+ "overdraw/res/values/strings.xml=>res/values/strings.xml",
+ "overdraw/res/values/styles.xml=>res/values/styles.xml",
+
+ // Java files must be renamed in source tree
+ "overdraw/gen/test/pkg/BuildConfig.java.txt=>gen/test/pkg/BuildConfig.java",
+ "overdraw/gen/test/pkg/R.java.txt=>gen/test/pkg/R.java",
+ "overdraw/src/test/pkg/FourthActivity.java.txt=>src/test/pkg/FourthActivity.java",
+ "overdraw/src/test/pkg/OverdrawActivity.java.txt=>src/test/pkg/OverdrawActivity.java",
+ "overdraw/src/test/pkg/SecondActivity.java.txt=>src/test/pkg/SecondActivity.java",
+ "overdraw/src/test/pkg/ThirdActivity.java.txt=>src/test/pkg/ThirdActivity.java"
+ ));
+ }
+
+} \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/OverrideDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/OverrideDetectorTest.java
new file mode 100644
index 0000000..68f80f9
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/OverrideDetectorTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class OverrideDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new OverrideDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/pkg2/Class2.java:7: Error: This package private method may be unintentionally overriding method in pkg1.Class1 [DalvikOverride]\n" +
+ " void method() { // Flag this as an accidental override\n" +
+ " ~~~~~~\n" +
+ " src/pkg1/Class1.java:4: This method is treated as overridden\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "src/pkg1/Class1.java.txt=>src/pkg1/Class1.java",
+ "src/pkg2/Class2.java.txt=>src/pkg2/Class2.java",
+ "bytecode/Class1.class.data=>bin/classes/pkg1/Class1.class",
+ "bytecode/Class1$Class4.class.data=>bin/classes/pkg1/Class1$Class4.class",
+ "bytecode/Class2.class.data=>bin/classes/pkg2/Class2.class",
+ "bytecode/Class2$Class3.class.data=>bin/classes/pkg2/Class2$Class3.class"
+ ));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/PrivateKeyDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/PrivateKeyDetectorTest.java
new file mode 100644
index 0000000..ff72dcb
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/PrivateKeyDetectorTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class PrivateKeyDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new PrivateKeyDetector();
+ }
+
+ @Override
+ protected boolean includeParentPath() {
+ return true;
+ }
+
+ public void testPrivateKey() throws Exception {
+ assertEquals(
+ "res/private_key.pem: Warning: The res/private_key.pem file seems to be a private key file. Please make sure not to embed this in your APK file. [PackagedPrivateKey]\n" +
+ "0 errors, 1 warnings\n",
+ lintProject(
+ // Not a private key file
+ "res/values/strings.xml=>res/values/strings/xml",
+ // Private key file
+ "res/private_key.pem=>res/private_key.pem"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/PrivateResourceDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/PrivateResourceDetectorTest.java
new file mode 100644
index 0000000..ce1b717
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/PrivateResourceDetectorTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class PrivateResourceDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new PrivateResourceDetector();
+ }
+
+ public void testPrivate() throws Exception {
+ assertEquals(
+ "res/layout/private.xml:3: Error: Illegal resource reference: @*android resources are private and not always present [PrivateResource]\n" +
+ " <ImageView android:id=\"@+id/android_logo\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:src=\"@*android:drawable/android_button\" android:focusable=\"false\" android:clickable=\"false\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n" +
+ "",
+ lintProject("res/layout/private.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ProguardDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ProguardDetectorTest.java
new file mode 100644
index 0000000..c493b8c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ProguardDetectorTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class ProguardDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ProguardDetector();
+ }
+
+ public void testProguard() throws Exception {
+ assertEquals(
+ "proguard.cfg:21: Error: Obsolete ProGuard file; use -keepclasseswithmembers instead of -keepclasseswithmembernames [Proguard]\n" +
+ "-keepclasseswithmembernames class * {\n" +
+ "^\n" +
+ "1 errors, 0 warnings\n" +
+ "",
+ lintFiles("proguard.cfg"));
+ }
+
+ public void testProguardNewPath() throws Exception {
+ assertEquals(
+ "proguard-project.txt:21: Error: Obsolete ProGuard file; use -keepclasseswithmembers instead of -keepclasseswithmembernames [Proguard]\n" +
+ "-keepclasseswithmembernames class * {\n" +
+ "^\n" +
+ "1 errors, 0 warnings\n" +
+ "",
+ lintFiles("proguard.cfg=>proguard-project.txt"));
+ }
+
+ public void testProguardRandomName() throws Exception {
+ assertEquals(
+ "myfile.txt:21: Error: Obsolete ProGuard file; use -keepclasseswithmembers instead of -keepclasseswithmembernames [Proguard]\n" +
+ "-keepclasseswithmembernames class * {\n" +
+ "^\n" +
+ "myfile.txt:8: Warning: Local ProGuard configuration contains general Android configuration: Inherit these settings instead? Modify project.properties to define proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:myfile.txt and then keep only project-specific configuration here [ProguardSplit]\n" +
+ "-keep public class * extends android.app.Activity\n" +
+ "^\n" +
+ "1 errors, 1 warnings\n" +
+ "",
+ lintProject(
+ "proguard.cfg=>myfile.txt",
+ "proguard.properties=>project.properties"));
+ }
+
+ public void testSilent() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles(
+ "proguard.pro=>proguard.cfg",
+ "project.properties1=>project.properties"));
+ }
+
+ public void testSilent2() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles(
+ "proguard.pro=>proguard.cfg",
+ "project.properties3=>project.properties"));
+ }
+
+ public void testSplit() throws Exception {
+ assertEquals(
+ "proguard.cfg:14: Warning: Local ProGuard configuration contains general Android configuration: Inherit these settings instead? Modify project.properties to define proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard.cfg and then keep only project-specific configuration here [ProguardSplit]\n" +
+ "-keep public class * extends android.app.Activity\n" +
+ "^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintFiles(
+ "proguard.pro=>proguard.cfg",
+ "project.properties2=>project.properties"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/PxUsageDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/PxUsageDetectorTest.java
new file mode 100644
index 0000000..68f218f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/PxUsageDetectorTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class PxUsageDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new PxUsageDetector();
+ }
+
+ public void testPx() throws Exception {
+ assertEquals(
+ "res/layout/now_playing_after.xml:49: Warning: Avoid using \"mm\" as units (it does not work accurately on all devices); use \"dp\" instead [InOrMmUsage]\n" +
+ " android:layout_width=\"100mm\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/now_playing_after.xml:50: Warning: Avoid using \"in\" as units (it does not work accurately on all devices); use \"dp\" instead [InOrMmUsage]\n" +
+ " android:layout_height=\"120in\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/now_playing_after.xml:41: Warning: Avoid using \"px\" as units; use \"dp\" instead [PxUsage]\n" +
+ " android:layout_width=\"1px\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 3 warnings\n",
+ lintFiles("res/layout/now_playing_after.xml"));
+ }
+
+ public void testSp() throws Exception {
+ assertEquals(
+ "res/layout/textsize.xml:11: Warning: Should use \"sp\" instead of \"dp\" for text sizes [SpUsage]\n" +
+ " android:textSize=\"14dp\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/textsize.xml:16: Warning: Should use \"sp\" instead of \"dp\" for text sizes [SpUsage]\n" +
+ " android:textSize=\"14dip\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/textsize.xml:33: Warning: Avoid using sizes smaller than 12sp: 11sp [SmallSp]\n" +
+ " android:textSize=\"11sp\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/textsize.xml:37: Warning: Avoid using sizes smaller than 12sp: 6sp [SmallSp]\n" +
+ " android:layout_height=\"6sp\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 4 warnings\n",
+
+ lintFiles("res/layout/textsize.xml"));
+ }
+
+ public void testStyles() throws Exception {
+ assertEquals(
+ "res/values/pxsp.xml:23: Warning: Avoid using \"mm\" as units (it does not work accurately on all devices); use \"dp\" instead [InOrMmUsage]\n" +
+ " <item name=\"android:textSize\">50mm</item>\n" +
+ " ^\n" +
+ "res/values/pxsp.xml:25: Warning: Avoid using \"in\" as units (it does not work accurately on all devices); use \"dp\" instead [InOrMmUsage]\n" +
+ " 50in\n" +
+ " ^\n" +
+ "res/values/pxsp.xml:6: Warning: Should use \"sp\" instead of \"dp\" for text sizes [SpUsage]\n" +
+ " <item name=\"android:textSize\">50dp</item>\n" +
+ " ^\n" +
+ "res/values/pxsp.xml:12: Warning: Should use \"sp\" instead of \"dp\" for text sizes [SpUsage]\n" +
+ " <item name=\"android:textSize\"> 50dip </item>\n" +
+ " ^\n" +
+ "res/values/pxsp.xml:9: Warning: Avoid using \"px\" as units; use \"dp\" instead [PxUsage]\n" +
+ " <item name=\"android:textSize\">50px</item>\n" +
+ " ^\n" +
+ "res/values/pxsp.xml:17: Warning: Avoid using \"px\" as units; use \"dp\" instead [PxUsage]\n" +
+ " <item name=\"android:paddingRight\"> 50px </item>\n" +
+ " ^\n" +
+ "res/values/pxsp.xml:18: Warning: Avoid using \"px\" as units; use \"dp\" instead [PxUsage]\n" +
+ " <item name=\"android:paddingTop\">50px</item>\n" +
+ " ^\n" +
+ "0 errors, 7 warnings\n",
+
+ lintFiles("res/values/pxsp.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/RegistrationDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/RegistrationDetectorTest.java
new file mode 100644
index 0000000..23a5ac3
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/RegistrationDetectorTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class RegistrationDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new RegistrationDetector();
+ }
+
+ public void testRegistered() throws Exception {
+ assertEquals(
+ "src/test/pkg/OnClickActivity.java:8: Warning: The <activity> test.pkg.OnClickActivity is not registered in the manifest [Registered]\n" +
+ "public class OnClickActivity extends Activity {\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/TestProvider.java:8: Warning: The <provider> test.pkg.TestProvider is not registered in the manifest [Registered]\n" +
+ "public class TestProvider extends ContentProvider {\n" +
+ " ~~~~~~~~~~~~\n" +
+ "src/test/pkg/TestProvider2.java:3: Warning: The <provider> test.pkg.TestProvider2 is not registered in the manifest [Registered]\n" +
+ "public class TestProvider2 extends TestProvider {\n" +
+ "^\n" +
+ "src/test/pkg/TestService.java:7: Warning: The <service> test.pkg.TestService is not registered in the manifest [Registered]\n" +
+ "public class TestService extends Service {\n" +
+ " ~~~~~~~~~~~\n" +
+ "0 errors, 4 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/OnClickActivity.java.txt=>src/test/pkg/OnClickActivity.java",
+ "bytecode/OnClickActivity.class.data=>bin/classes/test/pkg/OnClickActivity.class",
+ "bytecode/TestService.java.txt=>src/test/pkg/TestService.java",
+ "bytecode/TestService.class.data=>bin/classes/test/pkg/TestService.class",
+ "bytecode/TestProvider.java.txt=>src/test/pkg/TestProvider.java",
+ "bytecode/TestProvider.class.data=>bin/classes/test/pkg/TestProvider.class",
+ "bytecode/TestProvider2.java.txt=>src/test/pkg/TestProvider2.java",
+ "bytecode/TestProvider2.class.data=>bin/classes/test/pkg/TestProvider2.class",
+ "bytecode/TestReceiver.java.txt=>src/test/pkg/TestReceiver.java",
+ "bytecode/TestReceiver.class.data=>bin/classes/test/pkg/TestReceiver.class"
+ ));
+ }
+
+ public void testNoDot() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/AndroidManifestReg.xml=>AndroidManifest.xml",
+ "bytecode/.classpath=>.classpath",
+ "bytecode/CommentsActivity.java.txt=>src/test/pkg/Foo/CommentsActivity.java",
+ "bytecode/CommentsActivity.class.data=>bin/classes/test/pkg/Foo/CommentsActivity.class"
+ ));
+ }
+
+ public void testWrongRegistrations() throws Exception {
+ assertEquals(
+ "src/test/pkg/OnClickActivity.java:8: Warning: test.pkg.OnClickActivity is a <activity> but is registered in the manifest as a <receiver> [Registered]\n" +
+ "public class OnClickActivity extends Activity {\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/TestProvider.java:8: Warning: test.pkg.TestProvider is a <provider> but is registered in the manifest as a <activity> [Registered]\n" +
+ "public class TestProvider extends ContentProvider {\n" +
+ " ~~~~~~~~~~~~\n" +
+ "src/test/pkg/TestProvider2.java:3: Warning: test.pkg.TestProvider2 is a <provider> but is registered in the manifest as a <service> [Registered]\n" +
+ "public class TestProvider2 extends TestProvider {\n" +
+ "^\n" +
+ "src/test/pkg/TestReceiver.java:7: Warning: test.pkg.TestReceiver is a <receiver> but is registered in the manifest as a <service> [Registered]\n" +
+ "public class TestReceiver extends BroadcastReceiver {\n" +
+ " ~~~~~~~~~~~~\n" +
+ "src/test/pkg/TestService.java:7: Warning: test.pkg.TestService is a <service> but is registered in the manifest as a <provider> [Registered]\n" +
+ "public class TestService extends Service {\n" +
+ " ~~~~~~~~~~~\n" +
+ "0 errors, 5 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifestWrongRegs.xml=>AndroidManifest.xml",
+ "bytecode/OnClickActivity.java.txt=>src/test/pkg/OnClickActivity.java",
+ "bytecode/OnClickActivity.class.data=>bin/classes/test/pkg/OnClickActivity.class",
+ "bytecode/AbstractActivity.java.txt=>src/test/pkg/AbstractActivity.java",
+ "bytecode/AbstractActivity.class.data=>bin/classes/test/pkg/AbstractActivity.class",
+ "bytecode/TestService.java.txt=>src/test/pkg/TestService.java",
+ "bytecode/TestService.class.data=>bin/classes/test/pkg/TestService.class",
+ "bytecode/TestProvider.java.txt=>src/test/pkg/TestProvider.java",
+ "bytecode/TestProvider.class.data=>bin/classes/test/pkg/TestProvider.class",
+ "bytecode/TestProvider2.java.txt=>src/test/pkg/TestProvider2.java",
+ "bytecode/TestProvider2.class.data=>bin/classes/test/pkg/TestProvider2.class",
+ "bytecode/TestReceiver.java.txt=>src/test/pkg/TestReceiver.java",
+ "bytecode/TestReceiver.class.data=>bin/classes/test/pkg/TestReceiver.class",
+ "bytecode/TestReceiver$1.class.data=>bin/classes/test/pkg/TestReceiver$1.class"
+ ));
+ }
+
+ public void testLibraryProjects() throws Exception {
+ // If a library project provides additional activities, it is not an error to
+ // not register all of those here
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ // Master project
+ "multiproject/main-manifest.xml=>AndroidManifest.xml",
+ "multiproject/main.properties=>project.properties",
+
+ // Library project
+ "multiproject/library-manifest.xml=>../LibraryProject/AndroidManifest.xml",
+ "multiproject/library.properties=>../LibraryProject/project.properties",
+
+ "bytecode/.classpath=>../LibraryProject/.classpath",
+ "bytecode/OnClickActivity.java.txt=>../LibraryProject/src/test/pkg/OnClickActivity.java",
+ "bytecode/OnClickActivity.class.data=>../LibraryProject/bin/classes/test/pkg/OnClickActivity.class"
+ ));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/RequiredAttributeDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/RequiredAttributeDetectorTest.java
new file mode 100644
index 0000000..9b60532
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/RequiredAttributeDetectorTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class RequiredAttributeDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new RequiredAttributeDetector();
+ }
+
+ public void test() throws Exception {
+ // Simple: Only consider missing attributes in the layout xml file
+ // (though skip warnings on <merge> tags and under <GridLayout>
+ assertEquals(
+ "res/layout/size.xml:13: Error: The required layout_height attribute is missing [RequiredSize]\n" +
+ " <RadioButton\n" +
+ " ^\n" +
+ "res/layout/size.xml:18: Error: The required layout_width attribute is missing [RequiredSize]\n" +
+ " <EditText\n" +
+ " ^\n" +
+ "res/layout/size.xml:23: Error: The required layout_width and layout_height attributes are missing [RequiredSize]\n" +
+ " <EditText\n" +
+ " ^\n" +
+ "3 errors, 0 warnings\n",
+
+ lintProject("res/layout/size.xml"));
+ }
+
+ public void test2() throws Exception {
+ // Consider styles (specifying sizes) and includes (providing sizes for the root tags)
+ assertEquals(
+ "res/layout/size2.xml:9: Error: The required layout_width and layout_height attributes are missing [RequiredSize]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "res/layout/size2.xml:18: Error: The required layout_height attribute is missing [RequiredSize]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "2 errors, 0 warnings\n",
+
+ lintProject(
+ "res/layout/size2.xml",
+ "res/layout/sizeincluded.xml",
+ "res/values/sizestyles.xml"
+ ));
+ }
+
+ public void testInflaters() throws Exception {
+ // Consider java inflation
+ assertEquals(
+ "res/layout/size5.xml:2: Error: The required layout_width and layout_height attributes are missing [RequiredSize]\n" +
+ "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ "^\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject(
+ "src/test/pkg/InflaterTest.java.txt=>src/test/pkg/InflaterTest.java",
+ "res/layout/sizeincluded.xml=>res/layout/size1.xml",
+ "res/layout/sizeincluded.xml=>res/layout/size2.xml",
+ "res/layout/sizeincluded.xml=>res/layout/size3.xml",
+ "res/layout/sizeincluded.xml=>res/layout/size4.xml",
+ "res/layout/sizeincluded.xml=>res/layout/size5.xml",
+ "res/layout/sizeincluded.xml=>res/layout/size6.xml",
+ "res/layout/sizeincluded.xml=>res/layout/size7.xml"
+ ));
+ }
+
+ public void testRequestFocus() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=38700
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/layout/edit_type.xml"
+ ));
+ }
+
+ public void testFrameworkStyles() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=38958
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/layout/listseparator.xml"
+ ));
+ }
+
+ public void testThemeStyles() throws Exception {
+ // Check that we don't complain about cases where the size is defined in a theme
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/layout/size.xml",
+ "res/values/themes.xml"
+ ));
+ }
+
+ public void testThemeStyles2() throws Exception {
+ // Check that we don't complain about cases where the size is defined in a theme
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/layout/size.xml",
+ "res/values/themes2.xml"
+ ));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ScrollViewChildDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ScrollViewChildDetectorTest.java
new file mode 100644
index 0000000..ba79c50
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ScrollViewChildDetectorTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class ScrollViewChildDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ScrollViewChildDetector();
+ }
+
+ public void testScrollView() throws Exception {
+ assertEquals(
+ "res/layout/wrong_dimension.xml:10: Warning: This LinearLayout should use android:layout_width=\"wrap_content\" [ScrollViewSize]\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintFiles("res/layout/wrong_dimension.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/SdCardDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/SdCardDetectorTest.java
new file mode 100644
index 0000000..5ad46b9
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/SdCardDetectorTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class SdCardDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new SdCardDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/SdCardTest.java:13: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " private static final String SDCARD_TEST_HTML = \"/sdcard/test.html\";\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SdCardTest.java:14: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " public static final String SDCARD_ROOT = \"/sdcard\";\n" +
+ " ~~~~~~~~~\n" +
+ "src/test/pkg/SdCardTest.java:15: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " public static final String PACKAGES_PATH = \"/sdcard/o/packages/\";\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SdCardTest.java:16: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " File deviceDir = new File(\"/sdcard/vr\");\n" +
+ " ~~~~~~~~~~~~\n" +
+ "src/test/pkg/SdCardTest.java:20: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " android.os.Debug.startMethodTracing(\"/sdcard/launcher\");\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SdCardTest.java:22: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " if (new File(\"/sdcard\").exists()) {\n" +
+ " ~~~~~~~~~\n" +
+ "src/test/pkg/SdCardTest.java:24: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " String FilePath = \"/sdcard/\" + new File(\"test\");\n" +
+ " ~~~~~~~~~~\n" +
+ "src/test/pkg/SdCardTest.java:29: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " intent.setDataAndType(Uri.parse(\"file://sdcard/foo.json\"), \"application/bar-json\");\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SdCardTest.java:30: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " intent.putExtra(\"path-filter\", \"/sdcard(/.+)*\");\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SdCardTest.java:31: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " intent.putExtra(\"start-dir\", \"/sdcard\");\n" +
+ " ~~~~~~~~~\n" +
+ "src/test/pkg/SdCardTest.java:32: Warning: Do not hardcode \"/data/\"; use Context.getFilesDir().getPath() instead [SdCardPath]\n" +
+ " String mypath = \"/data/data/foo\";\n" +
+ " ~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SdCardTest.java:33: Warning: Do not hardcode \"/data/\"; use Context.getFilesDir().getPath() instead [SdCardPath]\n" +
+ " String base = \"/data/data/foo.bar/test-profiling\";\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SdCardTest.java:34: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " String s = \"file://sdcard/foo\";\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 13 warnings\n",
+
+ lintProject("src/test/pkg/SdCardTest.java.txt=>src/test/pkg/SdCardTest.java"));
+ }
+
+ public void testSuppress() throws Exception {
+ assertEquals(
+ // The only reference in the file not covered by an annotation
+ "src/test/pkg/SuppressTest5.java:40: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " String notAnnotated = \"/sdcard/mypath\";\n" +
+ " ~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ // File with lots of /sdcard references, but with @SuppressLint warnings
+ // on fields, methods, variable declarations etc
+ lintProject("src/test/pkg/SuppressTest5.java.txt=>src/test/pkg/SuppressTest5.java"));
+ }
+
+ public void testUtf8Bom() throws Exception {
+ assertEquals(
+ "src/test/pkg/Utf8BomTest.java:4: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" +
+ " String s = \"/sdcard/mydir\";\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject("src/test/pkg/Utf8BomTest.java.data=>src/test/pkg/Utf8BomTest.java"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/SecureRandomDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/SecureRandomDetectorTest.java
new file mode 100644
index 0000000..0ecbe02
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/SecureRandomDetectorTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class SecureRandomDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new SecureRandomDetector();
+ }
+
+ public void test1() throws Exception {
+ assertEquals(
+ "src/test/pkg/SecureRandomTest.java:12: Warning: It is dangerous to seed SecureRandom with the current time because that value is more predictable to an attacker than the default seed. [SecureRandom]\n" +
+ " random1.setSeed(System.currentTimeMillis()); // OK\n" +
+ " ~~~~~~~\n" +
+ "src/test/pkg/SecureRandomTest.java:14: Warning: Do not call setSeed() on a SecureRandom with a fixed seed: it is not secure. Use getSeed(). [SecureRandom]\n" +
+ " random1.setSeed(0); // Wrong\n" +
+ " ~~~~~~~\n" +
+ "src/test/pkg/SecureRandomTest.java:15: Warning: Do not call setSeed() on a SecureRandom with a fixed seed: it is not secure. Use getSeed(). [SecureRandom]\n" +
+ " random1.setSeed(1); // Wrong\n" +
+ " ~~~~~~~\n" +
+ "src/test/pkg/SecureRandomTest.java:16: Warning: Do not call setSeed() on a SecureRandom with a fixed seed: it is not secure. Use getSeed(). [SecureRandom]\n" +
+ " random1.setSeed((int)1023); // Wrong\n" +
+ " ~~~~~~~\n" +
+ "src/test/pkg/SecureRandomTest.java:17: Warning: Do not call setSeed() on a SecureRandom with a fixed seed: it is not secure. Use getSeed(). [SecureRandom]\n" +
+ " random1.setSeed(1023L); // Wrong\n" +
+ " ~~~~~~~\n" +
+ "src/test/pkg/SecureRandomTest.java:18: Warning: Do not call setSeed() on a SecureRandom with a fixed seed: it is not secure. Use getSeed(). [SecureRandom]\n" +
+ " random1.setSeed(FIXED_SEED); // Wrong\n" +
+ " ~~~~~~~\n" +
+ "src/test/pkg/SecureRandomTest.java:28: Warning: Do not call setSeed() on a SecureRandom with a fixed seed: it is not secure. Use getSeed(). [SecureRandom]\n" +
+ " random3.setSeed(0); // Wrong: owner is java/util/Random, but applied to SecureRandom object\n" +
+ " ~~~~~~~\n" +
+ "0 errors, 7 warnings\n" +
+ "",
+ // Missing error on line 40, using flow analysis to determine that the seed byte
+ // array passed into the SecureRandom constructor is static.
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "res/layout/onclick.xml=>res/layout/onclick.xml",
+ "bytecode/SecureRandomTest.java.txt=>src/test/pkg/SecureRandomTest.java",
+ "bytecode/SecureRandomTest.class.data=>bin/classes/test/pkg/SecureRandomTest.class"
+ ));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/SecurityDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/SecurityDetectorTest.java
new file mode 100644
index 0000000..1c293c3
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/SecurityDetectorTest.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class SecurityDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new SecurityDetector();
+ }
+
+ public void testBroken() throws Exception {
+ assertEquals(
+ "AndroidManifest.xml:12: Warning: Exported service does not require permission [ExportedService]\n" +
+ " <service\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject(
+ "exportservice1.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testBroken2() throws Exception {
+ assertEquals(
+ "AndroidManifest.xml:12: Warning: Exported service does not require permission [ExportedService]\n" +
+ " <service\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject(
+ "exportservice2.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testBroken3() throws Exception {
+ // Not defining exported, but have intent-filters
+ assertEquals(
+ "AndroidManifest.xml:12: Warning: Exported service does not require permission [ExportedService]\n" +
+ " <service\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject(
+ "exportservice5.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testOk1() throws Exception {
+ // Defines a permission on the <service> element
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "exportservice3.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testOk2() throws Exception {
+ // Defines a permission on the parent <application> element
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "exportservice4.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testUri() throws Exception {
+ assertEquals(
+ "AndroidManifest.xml:25: Warning: Content provider shares everything; this is potentially dangerous. [GrantAllUris]\n" +
+ " <grant-uri-permission android:path=\"/\"/>\n" +
+ " ~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:26: Warning: Content provider shares everything; this is potentially dangerous. [GrantAllUris]\n" +
+ " <grant-uri-permission android:pathPrefix=\"/\"/>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 2 warnings\n" +
+ "",
+
+ lintProject(
+ "grantpermission.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ // exportprovider1.xml has two exported content providers with no permissions
+ public void testContentProvider1() throws Exception {
+ assertEquals(
+ "AndroidManifest.xml:14: Warning: Exported content providers can provide access to potentially sensitive data [ExportedContentProvider]\n" +
+ " <provider\n" +
+ " ^\n" +
+ "AndroidManifest.xml:20: Warning: Exported content providers can provide access to potentially sensitive data [ExportedContentProvider]\n" +
+ " <provider\n" +
+ " ^\n" +
+ "0 errors, 2 warnings\n" +
+ "",
+ lintProject(
+ "exportprovider1.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ // exportprovider2.xml has no un-permissioned exported content providers
+ public void testContentProvider2() throws Exception {
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "exportprovider2.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testWorldWriteable() throws Exception {
+ assertEquals(
+ "src/test/pkg/WorldWriteableFile.java:26: Warning: Using MODE_WORLD_READABLE when creating files can be risky, review carefully [WorldReadableFiles]\n" +
+ " out = openFileOutput(mFile.getName(), MODE_WORLD_READABLE);\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/WorldWriteableFile.java:31: Warning: Using MODE_WORLD_READABLE when creating files can be risky, review carefully [WorldReadableFiles]\n" +
+ " prefs = getSharedPreferences(mContext, MODE_WORLD_READABLE);\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/WorldWriteableFile.java:25: Warning: Using MODE_WORLD_WRITEABLE when creating files can be risky, review carefully [WorldWriteableFiles]\n" +
+ " out = openFileOutput(mFile.getName(), MODE_WORLD_WRITEABLE);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/WorldWriteableFile.java:30: Warning: Using MODE_WORLD_WRITEABLE when creating files can be risky, review carefully [WorldWriteableFiles]\n" +
+ " prefs = getSharedPreferences(mContext, MODE_WORLD_WRITEABLE);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 4 warnings\n" +
+ "",
+
+ lintProject(
+ // Java files must be renamed in source tree
+ "src/test/pkg/WorldWriteableFile.java.txt=>src/test/pkg/WorldWriteableFile.java"));
+ }
+
+ public void testActivity0() throws Exception {
+ // Activities that do not have intent-filters do not need warnings
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "exportactivity0.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testActivity1() throws Exception {
+ assertEquals(
+ "AndroidManifest.xml:12: Warning: Exported activity does not require permission [ExportedActivity]\n" +
+ " <activity\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject(
+ "exportactivity1.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testActivity2() throws Exception {
+ // Defines a permission on the <activity> element
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "exportactivity2.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testActivity3() throws Exception {
+ // Defines a permission on the parent <application> element
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "exportactivity3.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testActivity4() throws Exception {
+ // Not defining exported, but have intent-filters
+ assertEquals(
+ "AndroidManifest.xml:12: Warning: Exported activity does not require permission [ExportedActivity]\n" +
+ " <activity\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject(
+ "exportactivity4.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testReceiver0() throws Exception {
+ // Activities that do not have intent-filters do not need warnings
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "exportreceiver0.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testReceiver1() throws Exception {
+ assertEquals(
+ "AndroidManifest.xml:12: Warning: Exported receiver does not require permission [ExportedReceiver]\n" +
+ " <receiver\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject(
+ "exportreceiver1.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testReceiver2() throws Exception {
+ // Defines a permission on the <activity> element
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "exportreceiver2.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testReceiver3() throws Exception {
+ // Defines a permission on the parent <application> element
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "exportreceiver3.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testReceiver4() throws Exception {
+ // Not defining exported, but have intent-filters
+ assertEquals(
+ "AndroidManifest.xml:12: Warning: Exported receiver does not require permission [ExportedReceiver]\n" +
+ " <receiver\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject(
+ "exportreceiver4.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testReceiver5() throws Exception {
+ // Intent filter for standard Android action
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "exportreceiver5.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testStandard() throws Exception {
+ // Various regression tests for http://code.google.com/p/android/issues/detail?id=33976
+ assertEquals(
+ "No warnings.",
+ lintProject("exportreceiver6.xml=>AndroidManifest.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/SetJavaScriptEnabledDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/SetJavaScriptEnabledDetectorTest.java
new file mode 100644
index 0000000..4979e6a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/SetJavaScriptEnabledDetectorTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class SetJavaScriptEnabledDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new SetJavaScriptEnabledDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/SetJavaScriptEnabled.java:14: Warning: Using setJavaScriptEnabled can introduce XSS vulnerabilities into you application, review carefully. [SetJavaScriptEnabled]\n" +
+ " webView.getSettings().setJavaScriptEnabled(true); // bad\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject(
+ "src/test/pkg/SetJavaScriptEnabled.java.txt=>src/test/pkg/SetJavaScriptEnabled.java"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/SharedPrefsDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/SharedPrefsDetectorTest.java
new file mode 100644
index 0000000..7035c21
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/SharedPrefsDetectorTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class SharedPrefsDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new SharedPrefsDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/SharedPrefsTest.java:54: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " SharedPreferences.Editor editor = preferences.edit();\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SharedPrefsTest.java:62: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " SharedPreferences.Editor editor = preferences.edit();\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 2 warnings\n" +
+ "",
+
+ lintProject("src/test/pkg/SharedPrefsTest.java.txt=>" +
+ "src/test/pkg/SharedPrefsTest.java"));
+ }
+
+ public void test2() throws Exception {
+ // Regression test 1 for http://code.google.com/p/android/issues/detail?id=34322
+ assertEquals(
+ "src/test/pkg/SharedPrefsTest2.java:13: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " SharedPreferences.Editor editor = preferences.edit();\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SharedPrefsTest2.java:17: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " Editor editor = preferences.edit();\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 2 warnings\n",
+
+ lintProject("src/test/pkg/SharedPrefsTest2.java.txt=>" +
+ "src/test/pkg/SharedPrefsTest2.java"));
+ }
+
+ public void test3() throws Exception {
+ // Regression test 2 for http://code.google.com/p/android/issues/detail?id=34322
+ assertEquals(
+ "src/test/pkg/SharedPrefsTest3.java:13: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " Editor editor = preferences.edit();\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n",
+
+ lintProject("src/test/pkg/SharedPrefsTest3.java.txt=>" +
+ "src/test/pkg/SharedPrefsTest3.java"));
+ }
+
+ public void test4() throws Exception {
+ // Regression test 3 for http://code.google.com/p/android/issues/detail?id=34322
+ assertEquals(
+ "No warnings.",
+
+ lintProject("src/test/pkg/SharedPrefsTest4.java.txt=>" +
+ "src/test/pkg/SharedPrefsTest4.java"));
+ }
+
+ public void test5() throws Exception {
+ // Check fields too: http://code.google.com/p/android/issues/detail?id=39134
+ assertEquals(
+ "src/test/pkg/SharedPrefsTest5.java:16: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " mPreferences.edit().putString(PREF_FOO, \"bar\");\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SharedPrefsTest5.java:17: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " mPreferences.edit().remove(PREF_BAZ).remove(PREF_FOO);\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SharedPrefsTest5.java:26: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " preferences.edit().putString(PREF_FOO, \"bar\");\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SharedPrefsTest5.java:27: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " preferences.edit().remove(PREF_BAZ).remove(PREF_FOO);\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SharedPrefsTest5.java:32: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " preferences.edit().putString(PREF_FOO, \"bar\");\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SharedPrefsTest5.java:33: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " preferences.edit().remove(PREF_BAZ).remove(PREF_FOO);\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SharedPrefsTest5.java:38: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " Editor editor = preferences.edit().putString(PREF_FOO, \"bar\");\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 7 warnings\n",
+
+ lintProject("src/test/pkg/SharedPrefsTest5.java.txt=>" +
+ "src/test/pkg/SharedPrefsTest5.java"));
+ }
+
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/StateListDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/StateListDetectorTest.java
new file mode 100644
index 0000000..9ff67f4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/StateListDetectorTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class StateListDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new StateListDetector();
+ }
+
+ public void testStates() throws Exception {
+ assertEquals(
+ "res/drawable/states.xml:3: Warning: This item is unreachable because a previous item (item #1) is a more general match than this one [StateListReachable]\n" +
+ " <item android:state_pressed=\"true\"\n" +
+ " ^\n" +
+ " res/drawable/states.xml:2: Earlier item which masks item\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject("res/drawable/states.xml"));
+ }
+
+ public void testCustomStates() throws Exception {
+ assertEquals(
+ "No warnings.",
+ lintProject("res/drawable/states2.xml"));
+ }
+
+ public void testStates3() throws Exception {
+ assertEquals(
+ "res/drawable/states3.xml:24: Warning: This item is unreachable because a previous item (item #1) is a more general match than this one [StateListReachable]\n" +
+ " <item android:state_checked=\"false\" android:state_window_focused=\"false\"\n" +
+ " ^\n" +
+ " res/drawable/states3.xml:18: Earlier item which masks item\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject("res/drawable/states3.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/StringFormatDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/StringFormatDetectorTest.java
new file mode 100644
index 0000000..a49955b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/StringFormatDetectorTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import static com.android.tools.lint.checks.StringFormatDetector.isLocaleSpecific;
+
+import com.android.tools.lint.detector.api.Detector;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@SuppressWarnings("javadoc")
+public class StringFormatDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new StringFormatDetector();
+ }
+
+ public void testAll() throws Exception {
+ assertEquals(
+ "src/test/pkg/StringFormatActivity.java:13: Error: Wrong argument type for formatting argument '#1' in hello: conversion is 'd', received String [StringFormatMatches]\n" +
+ " String output1 = String.format(hello, target);\n" +
+ " ~~~~~~\n" +
+ " res/values-es/formatstrings.xml:3: Conflicting argument declaration here\n" +
+ "src/test/pkg/StringFormatActivity.java:15: Error: Wrong argument count, format string hello2 requires 3 but format call supplies 2 [StringFormatMatches]\n" +
+ " String output2 = String.format(hello2, target, \"How are you\");\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/values-es/formatstrings.xml:4: This definition requires 3 arguments\n" +
+ "src/test/pkg/StringFormatActivity.java:24: Error: Wrong argument count, format string hello2 requires 3 but format call supplies 2 [StringFormatMatches]\n" +
+ " String.format(getResources().getString(R.string.hello2), target, \"How are you\");\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/values-es/formatstrings.xml:4: This definition requires 3 arguments\n" +
+ "src/test/pkg/StringFormatActivity.java:25: Error: Wrong argument count, format string hello2 requires 3 but format call supplies 2 [StringFormatMatches]\n" +
+ " getResources().getString(hello2, target, \"How are you\");\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/values-es/formatstrings.xml:4: This definition requires 3 arguments\n" +
+ "src/test/pkg/StringFormatActivity.java:26: Error: Wrong argument count, format string hello2 requires 3 but format call supplies 2 [StringFormatMatches]\n" +
+ " getResources().getString(R.string.hello2, target, \"How are you\");\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/values-es/formatstrings.xml:4: This definition requires 3 arguments\n" +
+ "src/test/pkg/StringFormatActivity.java:33: Error: Wrong argument type for formatting argument '#1' in hello: conversion is 'd', received String [StringFormatMatches]\n" +
+ " String output1 = String.format(hello, target);\n" +
+ " ~~~~~~\n" +
+ " res/values-es/formatstrings.xml:3: Conflicting argument declaration here\n" +
+ "res/values-es/formatstrings.xml:3: Error: Inconsistent formatting types for argument #1 in format string hello ('%1$d'): Found both 's' and 'd' (in values/formatstrings.xml) [StringFormatMatches]\n" +
+ " <string name=\"hello\">%1$d</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/values/formatstrings.xml:3: Conflicting argument type here\n" +
+ "res/values-es/formatstrings.xml:4: Warning: Inconsistent number of arguments in formatting string hello2; found both 2 and 3 [StringFormatCount]\n" +
+ " <string name=\"hello2\">%3$d: %1$s, %2$s?</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/values/formatstrings.xml:4: Conflicting number of arguments here\n" +
+ "res/values/formatstrings.xml:5: Warning: Formatting string 'missing' is not referencing numbered arguments [1, 2] [StringFormatCount]\n" +
+ " <string name=\"missing\">Hello %3$s World</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "7 errors, 2 warnings\n" +
+ "",
+
+ lintProject(
+ "res/values/formatstrings.xml",
+ "res/values-es/formatstrings.xml",
+ // Java files must be renamed in source tree
+ "src/test/pkg/StringFormatActivity.java.txt=>src/test/pkg/StringFormatActivity.java"
+ ));
+ }
+
+ public void testArgCount() {
+ assertEquals(3, StringFormatDetector.getFormatArgumentCount(
+ "First: %1$s, Second %2$s, Third %3$s", null));
+ assertEquals(11, StringFormatDetector.getFormatArgumentCount(
+ "Skipping stuff: %11$s", null));
+ assertEquals(1, StringFormatDetector.getFormatArgumentCount(
+ "First: %1$s, Skip \\%2$s", null));
+ assertEquals(1, StringFormatDetector.getFormatArgumentCount(
+ "First: %s, Skip \\%s", null));
+
+ Set<Integer> indices = new HashSet<Integer>();
+ assertEquals(11, StringFormatDetector.getFormatArgumentCount(
+ "Skipping stuff: %2$d %11$s", indices));
+ assertEquals(2, indices.size());
+ assertTrue(indices.contains(2));
+ assertTrue(indices.contains(11));
+ }
+
+ public void testArgType() {
+ assertEquals("s", StringFormatDetector.getFormatArgumentType(
+ "First: %1$s, Second %2$s, Third %3$s", 1));
+ assertEquals("d", StringFormatDetector.getFormatArgumentType(
+ "First: %1$s, Second %2$-5d, Third %3$s", 2));
+ assertEquals("s", StringFormatDetector.getFormatArgumentType(
+ "Skipping stuff: %11$s",11));
+ assertEquals("d", StringFormatDetector.getFormatArgumentType(
+ "First: %1$s, Skip \\%2$s, Value=%2$d", 2));
+ }
+
+ public void testWrongSyntax() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/values/formatstrings2.xml"
+ ));
+ }
+
+ public void testDateStrings() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/values/formatstrings-version1.xml=>res/values-tl/donottranslate-cldr.xml",
+ "res/values/formatstrings-version2.xml=>res/values/donottranslate-cldr.xml"
+ ));
+ }
+
+ public void testUa() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/values/formatstrings-version1.xml=>res/values-tl/donottranslate-cldr.xml",
+ "src/test/pkg/StringFormat2.java.txt=>src/test/pkg/StringFormat2.java"
+ ));
+ }
+
+ public void testSuppressed() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/values/formatstrings_ignore.xml=>res/values/formatstrings.xml",
+ "res/values-es/formatstrings_ignore.xml=>res/values-es/formatstrings.xml",
+ "src/test/pkg/StringFormatActivity_ignore.java.txt=>src/test/pkg/StringFormatActivity.java"
+ ));
+ }
+
+ public void testIssue27108() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject("res/values/formatstrings3.xml"));
+ }
+
+ public void testIssue39758() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/values/formatstrings4.xml",
+ "src/test/pkg/StringFormatActivity2.java.txt=>src/test/pkg/StringFormatActivity2.java"));
+ }
+
+ public void testIsLocaleSpecific() throws Exception {
+ assertFalse(isLocaleSpecific(""));
+ assertFalse(isLocaleSpecific("Hello World!"));
+ assertFalse(isLocaleSpecific("%% %n"));
+ assertFalse(isLocaleSpecific(" %%f"));
+ assertFalse(isLocaleSpecific("%x %A %c %b %B %h %n %%"));
+ assertTrue(isLocaleSpecific("%f"));
+ assertTrue(isLocaleSpecific(" %1$f "));
+ assertTrue(isLocaleSpecific(" %5$e "));
+ assertTrue(isLocaleSpecific(" %E "));
+ assertTrue(isLocaleSpecific(" %g "));
+ assertTrue(isLocaleSpecific(" %1$tm %1$te,%1$tY "));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/StyleCycleDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/StyleCycleDetectorTest.java
new file mode 100644
index 0000000..d4823d7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/StyleCycleDetectorTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class StyleCycleDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new StyleCycleDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/values/styles.xml:9: Error: Style DetailsPage_EditorialBuyButton should not extend itself [StyleCycle]\n" +
+ "<style name=\"DetailsPage_EditorialBuyButton\" parent=\"@style/DetailsPage_EditorialBuyButton\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n" +
+ "",
+
+ lintProject("res/values/styles.xml"));
+ }
+
+ public void test2() throws Exception {
+ assertEquals(
+ "res/values/stylecycle.xml:3: Error: Potential cycle: PropertyToggle is the implied parent of PropertyToggle.Base and this defines the opposite [StyleCycle]\n" +
+ " <style name=\"PropertyToggle\" parent=\"@style/PropertyToggle.Base\"></style>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n" +
+ "",
+
+ lintProject("res/values/stylecycle.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/SystemPermissionsDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/SystemPermissionsDetectorTest.java
new file mode 100644
index 0000000..061882c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/SystemPermissionsDetectorTest.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class SystemPermissionsDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new SystemPermissionsDetector();
+ }
+
+ public void testBrokenOrder() throws Exception {
+ assertEquals(
+ "AndroidManifest.xml:15: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:16: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.ACCESS_CACHE_FILESYSTEM\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:17: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.ACCESS_CHECKIN_PROPERTIES\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:18: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.ACCESS_MTP\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:19: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.ACCESS_SURFACE_FLINGER\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:20: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.ACCOUNT_MANAGER\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:21: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:22: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.ASEC_ACCESS\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:23: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.ASEC_CREATE\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:24: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.ASEC_DESTROY\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:25: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.ASEC_MOUNT_UNMOUNT\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:26: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.ASEC_RENAME\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:27: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BACKUP\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:28: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BIND_APPWIDGET\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:29: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BIND_DEVICE_ADMIN\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:30: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BIND_INPUT_METHOD\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:31: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BIND_PACKAGE_VERIFIER\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:32: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BIND_REMOTEVIEWS\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:33: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BIND_TEXT_SERVICE\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:34: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BIND_VPN_SERVICE\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:35: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BIND_WALLPAPER\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:36: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BRICK\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:37: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BROADCAST_PACKAGE_REMOVED\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:38: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BROADCAST_SMS\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:39: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.BROADCAST_WAP_PUSH\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:40: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.CALL_PRIVILEGED\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:41: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.CHANGE_BACKGROUND_DATA_SETTING\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:42: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.CHANGE_COMPONENT_ENABLED_STATE\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:43: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.CLEAR_APP_USER_DATA\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:44: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.CONFIRM_FULL_BACKUP\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:45: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.CONNECTIVITY_INTERNAL\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:46: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.CONTROL_LOCATION_UPDATES\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:47: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.COPY_PROTECTED_DATA\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:48: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.CRYPT_KEEPER\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:49: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.DELETE_CACHE_FILES\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:50: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.DELETE_PACKAGES\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:51: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.DEVICE_POWER\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:52: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.DIAGNOSTIC\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:53: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.DUMP\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:54: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.FACTORY_TEST\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:55: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.FORCE_BACK\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:56: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.FORCE_STOP_PACKAGES\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:57: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.GLOBAL_SEARCH\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:58: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.GLOBAL_SEARCH_CONTROL\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:59: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.HARDWARE_TEST\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:60: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.INJECT_EVENTS\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:61: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.INSTALL_LOCATION_PROVIDER\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:62: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.INSTALL_PACKAGES\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:63: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.INTERNAL_SYSTEM_WINDOW\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:64: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.MANAGE_APP_TOKENS\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:65: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.MANAGE_NETWORK_POLICY\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:66: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.MANAGE_USB\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:67: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.MASTER_CLEAR\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:68: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.MODIFY_NETWORK_ACCOUNTING\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:69: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.MODIFY_PHONE_STATE\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:70: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.MOVE_PACKAGE\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:71: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.NET_ADMIN\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:72: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.MODIFY_PHONE_STATE\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:73: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.PACKAGE_USAGE_STATS\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:74: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.PACKAGE_VERIFICATION_AGENT\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:75: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.PERFORM_CDMA_PROVISIONING\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:76: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.READ_FRAME_BUFFER\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:77: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.READ_INPUT_STATE\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:78: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.READ_NETWORK_USAGE_HISTORY\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:79: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.READ_PRIVILEGED_PHONE_STATE\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:80: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.REBOOT\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:81: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.RECEIVE_EMERGENCY_BROADCAST\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:82: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.REMOVE_TASKS\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:83: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.RETRIEVE_WINDOW_CONTENT\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:84: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.SEND_SMS_NO_CONFIRMATION\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:85: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.SET_ACTIVITY_WATCHER\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:86: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.SET_ORIENTATION\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:87: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.SET_POINTER_SPEED\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:88: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.SET_PREFERRED_APPLICATIONS\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:89: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.SET_SCREEN_COMPATIBILITY\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:90: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.SET_TIME\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:91: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.SET_WALLPAPER_COMPONENT\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:92: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.SHUTDOWN\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:93: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.STATUS_BAR\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:94: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.STATUS_BAR_SERVICE\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:95: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.STOP_APP_SWITCHES\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:96: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.UPDATE_DEVICE_STATS\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:97: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.WRITE_APN_SETTINGS\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:98: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.WRITE_GSERVICES\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:99: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.WRITE_MEDIA_STORAGE\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "AndroidManifest.xml:100: Error: Permission is only granted to system apps [ProtectedPermissions]\n" +
+ " <uses-permission android:name=\"android.permission.WRITE_SECURE_SETTINGS\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "86 errors, 0 warnings\n",
+
+ lintProject(
+ "protectedpermissions.xml=>AndroidManifest.xml"));
+ }
+
+ public void testSuppressed() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject("protectedpermissions2.xml=>AndroidManifest.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/TextFieldDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/TextFieldDetectorTest.java
new file mode 100644
index 0000000..795bc85
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/TextFieldDetectorTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class TextFieldDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new TextFieldDetector();
+ }
+
+ public void testField() throws Exception {
+ assertEquals(
+ "res/layout/note_edit.xml:50: Warning: This text field does not specify an inputType or a hint [TextFields]\n" +
+ " <EditText\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintFiles("res/layout/note_edit.xml"));
+ }
+
+ public void testTypeFromName() throws Exception {
+ assertEquals(
+ "res/layout/edit_type.xml:14: Warning: The view name (@+id/mypassword) suggests this is a password, but it does not include 'textPassword' in the inputType [TextFields]\n" +
+ " android:inputType=\"text\" >\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/layout/edit_type.xml:10: id defined here\n" +
+ "res/layout/edit_type.xml:45: Warning: The view name (@+id/password_length) suggests this is a number, but it does not include a numeric inputType (such as 'numberSigned') [TextFields]\n" +
+ " android:inputType=\"text\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/layout/edit_type.xml:41: id defined here\n" +
+ "res/layout/edit_type.xml:54: Warning: The view name (@+id/welcome_url) suggests this is a URI, but it does not include 'textUri' in the inputType [TextFields]\n" +
+ " android:inputType=\"text\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/layout/edit_type.xml:50: id defined here\n" +
+ "res/layout/edit_type.xml:63: Warning: The view name (@+id/start_date) suggests this is a date, but it does not include 'date' or 'datetime' in the inputType [TextFields]\n" +
+ " android:inputType=\"text\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/layout/edit_type.xml:59: id defined here\n" +
+ "res/layout/edit_type.xml:72: Warning: The view name (@+id/email_address) suggests this is an e-mail address, but it does not include 'textEmail' in the inputType [TextFields]\n" +
+ " android:inputType=\"text\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/layout/edit_type.xml:68: id defined here\n" +
+ "res/layout/edit_type.xml:81: Warning: The view name (@+id/login_pin) suggests this is a password, but it does not include 'numberPassword' in the inputType [TextFields]\n" +
+ " android:inputType=\"textPassword\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/layout/edit_type.xml:77: id defined here\n" +
+ "res/layout/edit_type.xml:83: Warning: This text field does not specify an inputType or a hint [TextFields]\n" +
+ " <EditText\n" +
+ " ^\n" +
+ "res/layout/edit_type.xml:84: Warning: The view name (@+id/number_of_items) suggests this is a number, but it does not include a numeric inputType (such as 'numberSigned') [TextFields]\n" +
+ " android:id=\"@+id/number_of_items\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 8 warnings\n",
+
+ lintFiles("res/layout/edit_type.xml"));
+ }
+
+ public void testContainsWord() {
+ assertFalse(containsWord("", "foob"));
+ assertFalse(containsWord("foo", "foob"));
+
+ assertTrue(containsWord("foo", "foo"));
+ assertTrue(containsWord("Foo", "foo"));
+ assertTrue(containsWord("foo_bar", "foo"));
+ assertTrue(containsWord("bar_foo", "foo"));
+ assertTrue(containsWord("bar_Foo", "foo"));
+ assertTrue(containsWord("bar_foo_baz", "foo"));
+ assertTrue(containsWord("bar_Foo_baz", "foo"));
+ assertTrue(containsWord("barFooBaz", "foo"));
+ assertTrue(containsWord("barFOO_", "foo"));
+ assertTrue(containsWord("FooBaz", "foo"));
+ assertTrue(containsWord("BarFoo", "foo"));
+ assertFalse(containsWord("barfoo", "foo"));
+ assertTrue(containsWord("barfoo", "foo", false, true));
+ assertTrue(containsWord("foobar", "foo", true, false));
+ assertFalse(containsWord("foobar", "foo"));
+ assertFalse(containsWord("barfoobar", "foo"));
+
+ assertTrue(containsWord("phoneNumber", "phone"));
+ assertTrue(containsWord("phoneNumber", "number"));
+ assertTrue(containsWord("uri_prefix", "uri"));
+ assertTrue(containsWord("fooURI", "uri"));
+ assertTrue(containsWord("my_url", "url"));
+ assertTrue(containsWord("network_prefix_length", "length"));
+
+ assertFalse(containsWord("sizer", "size"));
+ assertFalse(containsWord("synthesize_to_filename", "size"));
+ assertFalse(containsWord("update_text", "date"));
+ assertFalse(containsWord("daten", "date"));
+
+ assertFalse(containsWord("phonenumber", "phone"));
+ assertFalse(containsWord("myphone", "phone"));
+ assertTrue(containsWord("phonenumber", "phone", true, true));
+ assertTrue(containsWord("myphone", "phone", true, true));
+ assertTrue(containsWord("phoneNumber", "phone"));
+
+ assertTrue(containsWord("phoneNumber", "phone"));
+ assertTrue(containsWord("@id/phoneNumber", "phone"));
+ assertTrue(containsWord("@+id/phoneNumber", "phone"));
+ }
+
+ private static boolean containsWord(String name, String word, boolean allowPrefix,
+ boolean allowSuffix) {
+ return TextFieldDetector.containsWord(name, word, allowPrefix, allowSuffix);
+ }
+
+ private static boolean containsWord(String name, String word) {
+ return TextFieldDetector.containsWord(name, word);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/TextViewDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/TextViewDetectorTest.java
new file mode 100644
index 0000000..0ee144b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/TextViewDetectorTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class TextViewDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new TextViewDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/layout/edit_textview.xml:13: Warning: Attribute android:autoText should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:autoText=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:14: Warning: Attribute android:bufferType should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:bufferType=\"editable\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:15: Warning: Attribute android:capitalize should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:capitalize=\"words\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:16: Warning: Attribute android:cursorVisible should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:cursorVisible=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:17: Warning: Attribute android:digits should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:digits=\"\"\n" +
+ " ~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:18: Warning: Attribute android:editable should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:editable=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:19: Warning: Attribute android:editorExtras should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:editorExtras=\"@+id/foobar\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:22: Warning: Attribute android:imeActionId should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:imeActionId=\"@+id/foo\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:23: Warning: Attribute android:imeActionLabel should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:imeActionLabel=\"\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:24: Warning: Attribute android:imeOptions should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:imeOptions=\"\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:25: Warning: Attribute android:inputMethod should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:inputMethod=\"\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:26: Warning: Attribute android:inputType should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:inputType=\"text\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:27: Warning: Attribute android:numeric should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:numeric=\"\"\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:28: Warning: Attribute android:password should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:password=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:29: Warning: Attribute android:phoneNumber should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:phoneNumber=\"true\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:30: Warning: Attribute android:privateImeOptions should not be used with <TextView>: Change element type to <EditText> ? [TextViewEdits]\n" +
+ " android:privateImeOptions=\"\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:38: Warning: Attribute android:cursorVisible should not be used with <Button>: intended for editable text widgets [TextViewEdits]\n" +
+ " android:cursorVisible=\"true\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:44: Warning: Attribute android:cursorVisible should not be used with <CheckedTextView>: intended for editable text widgets [TextViewEdits]\n" +
+ " android:cursorVisible=\"true\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:50: Warning: Attribute android:cursorVisible should not be used with <CheckBox>: intended for editable text widgets [TextViewEdits]\n" +
+ " android:cursorVisible=\"true\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:56: Warning: Attribute android:cursorVisible should not be used with <RadioButton>: intended for editable text widgets [TextViewEdits]\n" +
+ " android:cursorVisible=\"true\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:62: Warning: Attribute android:cursorVisible should not be used with <ToggleButton>: intended for editable text widgets [TextViewEdits]\n" +
+ " android:cursorVisible=\"true\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/edit_textview.xml:83: Warning: Consider making the text value selectable by specifying android:textIsSelectable=\"true\" [SelectableText]\n" +
+ " <TextView\n" +
+ " ^\n" +
+ "0 errors, 22 warnings\n",
+
+ lintFiles(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml", // API >= 11 for selectable issue
+ "res/layout/edit_textview.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/TitleDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/TitleDetectorTest.java
new file mode 100644
index 0000000..7259cde
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/TitleDetectorTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class TitleDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new TitleDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/menu/titles.xml:3: Warning: Menu items should specify a title [MenuTitle]\n" +
+ " <item android:id=\"@+id/action_bar_progress_spinner\"\n" +
+ " ^\n" +
+ "res/menu/titles.xml:12: Warning: Menu items should specify a title [MenuTitle]\n" +
+ " <item android:id=\"@+id/menu_plus_one\"\n" +
+ " ^\n" +
+ "0 errors, 2 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/menu/titles.xml"));
+ }
+
+ public void testOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "res/menu/titles.xml"));
+ }
+
+ public void testOk2() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject("res/menu-land/actions.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ToastDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ToastDetectorTest.java
new file mode 100644
index 0000000..07941b7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ToastDetectorTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class ToastDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ToastDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/ToastTest.java:31: Warning: Toast created but not shown: did you forget to call show() ? [ShowToast]\n" +
+ " Toast.makeText(context, \"foo\", Toast.LENGTH_LONG);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/ToastTest.java:32: Warning: Expected duration Toast.LENGTH_SHORT or Toast.LENGTH_LONG, a custom duration value is not supported [ShowToast]\n" +
+ " Toast toast = Toast.makeText(context, R.string.app_name, 5000);\n" +
+ " ~~~~\n" +
+ "src/test/pkg/ToastTest.java:32: Warning: Toast created but not shown: did you forget to call show() ? [ShowToast]\n" +
+ " Toast toast = Toast.makeText(context, R.string.app_name, 5000);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/ToastTest.java:38: Warning: Toast created but not shown: did you forget to call show() ? [ShowToast]\n" +
+ " Toast.makeText(context, \"foo\", Toast.LENGTH_LONG);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 4 warnings\n" +
+ "",
+
+ lintProject("src/test/pkg/ToastTest.java.txt=>src/test/pkg/ToastTest.java"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/TooManyViewsDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/TooManyViewsDetectorTest.java
new file mode 100644
index 0000000..51b977d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/TooManyViewsDetectorTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class TooManyViewsDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new TooManyViewsDetector();
+ }
+
+ public void testTooMany() throws Exception {
+ assertEquals(
+ "res/layout/too_many.xml:399: Warning: too_many.xml has more than 80 views, bad for performance [TooManyViews]\n" +
+ " <Button\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintFiles("res/layout/too_many.xml"));
+ }
+
+ public void testTooDeep() throws Exception {
+ assertEquals(
+ "res/layout/too_deep.xml:46: Warning: too_deep.xml has more than 10 levels, bad for performance [TooDeepLayout]\n" +
+ " <LinearLayout\n" +
+ " ^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintFiles("res/layout/too_deep.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/TranslationDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/TranslationDetectorTest.java
new file mode 100644
index 0000000..7a9830b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/TranslationDetectorTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class TranslationDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new TranslationDetector();
+ }
+
+ @Override
+ protected boolean includeParentPath() {
+ return true;
+ }
+
+ public void testTranslation() throws Exception {
+ TranslationDetector.COMPLETE_REGIONS = false;
+ assertEquals(
+ // Sample files from the Home app
+ "res/values/strings.xml:20: Error: \"show_all_apps\" is not translated in nl-rNL [MissingTranslation]\n" +
+ " <string name=\"show_all_apps\">All</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/values/strings.xml:23: Error: \"menu_wallpaper\" is not translated in nl-rNL [MissingTranslation]\n" +
+ " <string name=\"menu_wallpaper\">Wallpaper</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/values/strings.xml:25: Error: \"menu_settings\" is not translated in cs, de-rDE, es, es-rUS, nl-rNL [MissingTranslation]\n" +
+ " <string name=\"menu_settings\">Settings</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/values-cs/arrays.xml:3: Error: \"security_questions\" is translated here but not found in default locale [ExtraTranslation]\n" +
+ " <string-array name=\"security_questions\">\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/values-es/strings.xml:12: Also translated here\n" +
+ "res/values-de-rDE/strings.xml:11: Error: \"continue_skip_label\" is translated here but not found in default locale [ExtraTranslation]\n" +
+ " <string name=\"continue_skip_label\">\"Weiter\"</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "5 errors, 0 warnings\n" +
+ "",
+
+ lintProject(
+ "res/values/strings.xml",
+ "res/values-cs/strings.xml",
+ "res/values-de-rDE/strings.xml",
+ "res/values-es/strings.xml",
+ "res/values-es-rUS/strings.xml",
+ "res/values-land/strings.xml",
+ "res/values-cs/arrays.xml",
+ "res/values-es/donottranslate.xml",
+ "res/values-nl-rNL/strings.xml"));
+ }
+
+ public void testTranslationWithCompleteRegions() throws Exception {
+ TranslationDetector.COMPLETE_REGIONS = true;
+ assertEquals(
+ // Sample files from the Home app
+ "res/values/strings.xml:19: Error: \"home_title\" is not translated in es-rUS [MissingTranslation]\n" +
+ " <string name=\"home_title\">Home Sample</string>\n" +
+ " ~~~~~~~~~~~~~~~~~\n" +
+ "res/values/strings.xml:20: Error: \"show_all_apps\" is not translated in es-rUS, nl-rNL [MissingTranslation]\n" +
+ " <string name=\"show_all_apps\">All</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/values/strings.xml:23: Error: \"menu_wallpaper\" is not translated in es-rUS, nl-rNL [MissingTranslation]\n" +
+ " <string name=\"menu_wallpaper\">Wallpaper</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/values/strings.xml:25: Error: \"menu_settings\" is not translated in cs, de-rDE, es-rUS, nl-rNL [MissingTranslation]\n" +
+ " <string name=\"menu_settings\">Settings</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/values/strings.xml:29: Error: \"wallpaper_instructions\" is not translated in es-rUS [MissingTranslation]\n" +
+ " <string name=\"wallpaper_instructions\">Tap picture to set portrait wallpaper</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ " res/values-land/strings.xml:19: <No location-specific message\n" +
+ "res/values-de-rDE/strings.xml:11: Error: \"continue_skip_label\" is translated here but not found in default locale [ExtraTranslation]\n" +
+ " <string name=\"continue_skip_label\">\"Weiter\"</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "6 errors, 0 warnings\n" +
+ "",
+
+ lintProject(
+ "res/values/strings.xml",
+ "res/values-cs/strings.xml",
+ "res/values-de-rDE/strings.xml",
+ "res/values-es-rUS/strings.xml",
+ "res/values-land/strings.xml",
+ "res/values-nl-rNL/strings.xml"));
+ }
+
+ public void testHandleBom() throws Exception {
+ // This isn't really testing translation detection; it's just making sure that the
+ // XML parser doesn't bomb on BOM bytes (byte order marker) at the beginning of
+ // the XML document
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "res/values-de/strings.xml"
+ ));
+ }
+
+ public void testTranslatedArrays() throws Exception {
+ TranslationDetector.COMPLETE_REGIONS = true;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/values/translatedarrays.xml",
+ "res/values-cs/translatedarrays.xml"));
+ }
+
+ public void testTranslationSuppresss() throws Exception {
+ TranslationDetector.COMPLETE_REGIONS = false;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/values/strings_ignore.xml=>res/values/strings.xml",
+ "res/values-es/strings_ignore.xml=>res/values-es/strings.xml",
+ "res/values-nl-rNL/strings.xml=>res/values-nl-rNL/strings.xml"));
+ }
+
+ public void testMixedTranslationArrays() throws Exception {
+ // See issue http://code.google.com/p/android/issues/detail?id=29263
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/values/strings3.xml=>res/values/strings.xml",
+ "res/values-fr/strings.xml=>res/values-fr/strings.xml"));
+ }
+
+ public void testLibraryProjects() throws Exception {
+ // If a library project provides additional locales, that should not force
+ // the main project to include all those translations
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ // Master project
+ "multiproject/main-manifest.xml=>AndroidManifest.xml",
+ "multiproject/main.properties=>project.properties",
+ "res/values/strings2.xml",
+
+ // Library project
+ "multiproject/library-manifest.xml=>../LibraryProject/AndroidManifest.xml",
+ "multiproject/library.properties=>../LibraryProject/project.properties",
+
+ "res/values/strings.xml=>../LibraryProject/res/values/strings.xml",
+ "res/values-cs/strings.xml=>../LibraryProject/res/values-cs/strings.xml",
+ "res/values-cs/strings.xml=>../LibraryProject/res/values-de/strings.xml",
+ "res/values-cs/strings.xml=>../LibraryProject/res/values-nl/strings.xml"
+ ));
+ }
+
+ public void testNonTranslatable1() throws Exception {
+ TranslationDetector.COMPLETE_REGIONS = true;
+ assertEquals(
+ "res/values-nb/nontranslatable.xml:3: Error: The resource string \"dummy\" has been marked as translatable=\"false\" [ExtraTranslation]\n" +
+ " <string name=\"dummy\">Ignore Me</string>\n" +
+ " ~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n" +
+ "",
+
+ lintProject("res/values/nontranslatable.xml",
+ "res/values/nontranslatable2.xml=>res/values-nb/nontranslatable.xml"));
+ }
+
+ public void testNonTranslatable2() throws Exception {
+ TranslationDetector.COMPLETE_REGIONS = true;
+ assertEquals(
+ "res/values-nb/nontranslatable.xml:3: Error: Non-translatable resources should only be defined in the base values/ folder [ExtraTranslation]\n" +
+ " <string name=\"dummy\" translatable=\"false\">Ignore Me</string>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n" +
+ "",
+
+ lintProject("res/values/nontranslatable.xml=>res/values-nb/nontranslatable.xml"));
+ }
+
+ public void testSpecifiedLanguageOk() throws Exception {
+ TranslationDetector.COMPLETE_REGIONS = false;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/values-es/strings.xml=>res/values-es/strings.xml",
+ "res/values-es-rUS/strings.xml"));
+ }
+
+ public void testSpecifiedLanguage() throws Exception {
+ TranslationDetector.COMPLETE_REGIONS = false;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/values-es/strings_locale.xml=>res/values/strings.xml",
+ "res/values-es-rUS/strings.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/TypoDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/TypoDetectorTest.java
new file mode 100644
index 0000000..3c49b3a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/TypoDetectorTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+import java.util.Arrays;
+
+@SuppressWarnings("javadoc")
+public class TypoDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new TypoDetector();
+ }
+
+ public void testPlainValues() throws Exception {
+ assertEquals(
+ "res/values/strings.xml:6: Warning: \"Andriod\" is a common misspelling; did you mean \"Android\" ? [Typos]\n" +
+ " <string name=\"s2\">Andriod activites!</string>\n" +
+ " ^\n" +
+ "res/values/strings.xml:6: Warning: \"activites\" is a common misspelling; did you mean \"activities\" ? [Typos]\n" +
+ " <string name=\"s2\">Andriod activites!</string>\n" +
+ " ^\n" +
+ "res/values/strings.xml:8: Warning: \"Cmoputer\" is a common misspelling; did you mean \"Computer\" ? [Typos]\n" +
+ " <string name=\"s3\"> (Cmoputer </string>\n" +
+ " ^\n" +
+ "res/values/strings.xml:10: Warning: \"throught\" is a common misspelling; did you mean \"thought\" or \"through\" or \"throughout\" ? [Typos]\n" +
+ " <string name=\"s4\"><b>throught</b></string>\n" +
+ " ^\n" +
+ "res/values/strings.xml:12: Warning: \"Seach\" is a common misspelling; did you mean \"Search\" ? [Typos]\n" +
+ " <string name=\"s5\">Seach</string>\n" +
+ " ^\n" +
+ "res/values/strings.xml:16: Warning: \"Tuscon\" is a common misspelling; did you mean \"Tucson\" ? [Typos]\n" +
+ " <string name=\"s7\">Tuscon tuscon</string>\n" +
+ " ^\n" +
+ "res/values/strings.xml:20: Warning: \"Ok\" is usually capitalized as \"OK\" [Typos]\n" +
+ " <string name=\"dlg_button_ok\">Ok</string>\n" +
+ " ^\n" +
+ "0 errors, 7 warnings\n" +
+ "",
+ lintProject("res/values/typos.xml=>res/values/strings.xml"));
+ }
+
+ public void testEnLanguage() throws Exception {
+ assertEquals(
+ "res/values-en-rUS/strings-en.xml:6: Warning: \"Andriod\" is a common misspelling; did you mean \"Android\" ? [Typos]\n" +
+ " <string name=\"s2\">Andriod activites!</string>\n" +
+ " ^\n" +
+ "res/values-en-rUS/strings-en.xml:6: Warning: \"activites\" is a common misspelling; did you mean \"activities\" ? [Typos]\n" +
+ " <string name=\"s2\">Andriod activites!</string>\n" +
+ " ^\n" +
+ "res/values-en-rUS/strings-en.xml:8: Warning: \"Cmoputer\" is a common misspelling; did you mean \"Computer\" ? [Typos]\n" +
+ " <string name=\"s3\"> (Cmoputer </string>\n" +
+ " ^\n" +
+ "res/values-en-rUS/strings-en.xml:10: Warning: \"throught\" is a common misspelling; did you mean \"thought\" or \"through\" or \"throughout\" ? [Typos]\n" +
+ " <string name=\"s4\"><b>throught</b></string>\n" +
+ " ^\n" +
+ "res/values-en-rUS/strings-en.xml:12: Warning: \"Seach\" is a common misspelling; did you mean \"Search\" ? [Typos]\n" +
+ " <string name=\"s5\">Seach</string>\n" +
+ " ^\n" +
+ "res/values-en-rUS/strings-en.xml:16: Warning: \"Tuscon\" is a common misspelling; did you mean \"Tucson\" ? [Typos]\n" +
+ " <string name=\"s7\">Tuscon tuscon</string>\n" +
+ " ^\n" +
+ "res/values-en-rUS/strings-en.xml:20: Warning: \"Ok\" is usually capitalized as \"OK\" [Typos]\n" +
+ " <string name=\"dlg_button_ok\">Ok</string>\n" +
+ " ^\n" +
+ "0 errors, 7 warnings\n" +
+ "",
+ lintProject("res/values/typos.xml=>res/values-en-rUS/strings-en.xml"));
+ }
+
+ public void testNorwegian() throws Exception {
+ // UTF-8 handling
+ assertEquals(
+ "res/values-nb/typos.xml:6: Warning: \"Andriod\" is a common misspelling; did you mean \"Android\" ? [Typos]\n" +
+ " <string name=\"s2\">Mer morro med Andriod</string>\n" +
+ " ^\n" +
+ "res/values-nb/typos.xml:6: Warning: \"morro\" is a common misspelling; did you mean \"moro\" ? [Typos]\n" +
+ " <string name=\"s2\">Mer morro med Andriod</string>\n" +
+ " ^\n" +
+ "res/values-nb/typos.xml:8: Warning: \"Parallel\" is a common misspelling; did you mean \"Parallell\" ? [Typos]\n" +
+ " <string name=\"s3\"> Parallel </string>\n" +
+ " ^\n" +
+ "res/values-nb/typos.xml:10: Warning: \"altid\" is a common misspelling; did you mean \"alltid\" ? [Typos]\n" +
+ " <string name=\"s4\"><b>altid</b></string>\n" +
+ " ^\n" +
+ "res/values-nb/typos.xml:12: Warning: \"Altid\" is a common misspelling; did you mean \"Alltid\" ? [Typos]\n" +
+ " <string name=\"s5\">Altid</string>\n" +
+ " ^\n" +
+ "res/values-nb/typos.xml:18: Warning: \"karriære\" is a common misspelling; did you mean \"karrière\" ? [Typos]\n" +
+ " <string name=\"s7\">Koding er en spennende karriære</string>\n" +
+ " ^\n" +
+ "0 errors, 6 warnings\n" +
+ "",
+ lintProject("res/values-nb/typos.xml"));
+ }
+
+ public void testGerman() throws Exception {
+ // Test globbing and multiple word matching
+ assertEquals(
+ "res/values-de/typos.xml:6: Warning: \"befindet eine\" is a common misspelling; did you mean \"befindet sich eine\" ? [Typos]\n" +
+ " wo befindet eine ip\n" +
+ " ^\n" +
+ "res/values-de/typos.xml:9: Warning: \"Authorisierungscode\" is a common misspelling; did you mean \"Autorisierungscode\" ? [Typos]\n" +
+ " <string name=\"s2\">(Authorisierungscode!)</string>\n" +
+ " ^\n" +
+ "res/values-de/typos.xml:10: Warning: \"zurück gefoobaren\" is a common misspelling; did you mean \"zurückgefoobaren\" ? [Typos]\n" +
+ " <string name=\"s3\"> zurück gefoobaren!</string>\n" +
+ " ^\n" +
+ "0 errors, 3 warnings\n" +
+ "",
+ lintProject("res/values-de/typos.xml"));
+ }
+
+ public void testOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+ lintProject("res/values/typos.xml=>res/values-xy/strings.xml"));
+ }
+
+ public void testGetReplacements() {
+ String s = "\"throught\" is a common misspelling; did you mean \"thought\" or " +
+ "\"through\" or \"throughout\" ?\n";
+ assertEquals("throught", TypoDetector.getTypo(s));
+ assertEquals(Arrays.asList("thought", "through", "throughout"),
+ TypoDetector.getSuggestions(s));
+ }
+
+ public void testNorwegianDefault() throws Exception {
+ assertEquals(
+ "res/values/typos.xml:5: Warning: \"altid\" is a common misspelling; did you mean \"alltid\" ? [Typos]\n" +
+ " <string name=\"s4\"><b>altid</b></string>\n" +
+ " ^\n" +
+ "res/values/typos.xml:7: Warning: \"Altid\" is a common misspelling; did you mean \"Alltid\" ? [Typos]\n" +
+ " <string name=\"s5\">Altid</string>\n" +
+ " ^\n" +
+ "0 errors, 2 warnings\n",
+
+ lintProject("res/values-nb/typos_locale.xml=>res/values/typos.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/TypoLookupTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/TypoLookupTest.java
new file mode 100644
index 0000000..e57b8ce
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/TypoLookupTest.java
@@ -0,0 +1,523 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.client.api.LintClient;
+import com.android.tools.lint.detector.api.Detector;
+import com.google.common.base.Charsets;
+import com.google.common.base.Splitter;
+import com.google.common.io.Files;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+@SuppressWarnings("javadoc")
+public class TypoLookupTest extends AbstractCheckTest {
+ private static final String SEPARATOR = "->";
+
+ public void testCapitalization() throws Exception {
+ LintClient client = new TestLintClient();
+ // Make sure it can be read in
+ TypoLookup db = TypoLookup.get(client, "de", null);
+ assertNotNull(db);
+ assertNotNull(db.getTypos("Andriod".getBytes(Charsets.UTF_8), 0, "Andriod".length()));
+ }
+
+ public void testDictionary_English() throws Exception {
+ validateDictionary("en");
+ }
+
+ public void testDictionary_German() throws Exception {
+ validateDictionary("de");
+ }
+
+ public void testDictionary_Spanish() throws Exception {
+ validateDictionary("es");
+ }
+
+ public void testDictionary_Hungarian() throws Exception {
+ validateDictionary("hu");
+ }
+
+ public void testDictionary_Italian() throws Exception {
+ validateDictionary("it");
+ }
+
+ public void testDictionary_Norwegian() throws Exception {
+ validateDictionary("nb");
+ }
+
+ public void testDictionary_Portuguese() throws Exception {
+ validateDictionary("pt");
+ }
+
+ public void testDictionary_Turkish() throws Exception {
+ validateDictionary("tr");
+ }
+
+ public void test1() {
+ TypoLookup db = TypoLookup.get(new TestLintClient(), "en", null);
+ assertNull(db.getTypos("hello", 0, "hello".length()));
+ assertNull(db.getTypos("this", 0, "this".length()));
+
+ assertNotNull(db.getTypos("wiht", 0, "wiht".length()));
+ assertNotNull(db.getTypos("woudl", 0, "woudl".length()));
+ assertEquals("would", db.getTypos("woudl", 0, "woudl".length()).get(1));
+ assertEquals("would", db.getTypos(" woudl ", 2, 7).get(1));
+ assertNotNull(db.getTypos("foo wiht bar", 4, 8));
+
+ List<String> typos = db.getTypos("throught", 0, "throught".length());
+ assertEquals("throught", typos.get(0)); // the typo
+ assertEquals("thought", typos.get(1));
+ assertEquals("through", typos.get(2));
+ assertEquals("throughout", typos.get(3));
+
+ // Capitalization handling
+ assertNotNull(db.getTypos("Woudl", 0, "Woudl".length()));
+ assertNotNull(db.getTypos("Enlish", 0, "Enlish".length()));
+ assertNull(db.getTypos("enlish", 0, "enlish".length()));
+ assertNull(db.getTypos("enlish".getBytes(Charsets.UTF_8), 0, "enlish".length()));
+ assertNotNull(db.getTypos("ok", 0, "ok".length()));
+ assertNotNull(db.getTypos("Ok", 0, "Ok".length()));
+ assertNull(db.getTypos("OK", 0, "OK".length()));
+ }
+
+ public void testRegion() {
+ TypoLookup db = TypoLookup.get(new TestLintClient(), "en", "US");
+ assertNotNull(db.getTypos("wiht", 0, "wiht".length()));
+ db = TypoLookup.get(new TestLintClient(), "en", "GB");
+ assertNotNull(db.getTypos("wiht", 0, "wiht".length()));
+ }
+
+ public void test2() {
+ TypoLookup db = TypoLookup.get(new TestLintClient(), "nb", null); //$NON-NLS-1$
+ assertNull(db.getTypos("hello", 0, "hello".length()));
+ assertNull(db.getTypos("this", 0, "this".length()));
+
+ assertNotNull(db.getTypos("altid", 0, "altid".length()));
+ assertEquals("alltid", db.getTypos("altid", 0, "altid".length()).get(1));
+ assertEquals("alltid", db.getTypos(" altid ", 2, 7).get(1));
+ assertNotNull(db.getTypos("foo altid bar", 4, 9));
+
+ // Test utf-8 string which isn't ASCII
+ String s = "karriære";
+ byte[] sb = s.getBytes(Charsets.UTF_8);
+ assertNotNull(db.getTypos(sb, 0, sb.length));
+
+ assertEquals("karrière", db.getTypos(sb, 0, sb.length).get(1));
+ }
+
+ public void testMultiWords() {
+ // Some language dictionaries contain multi-word sequences (e.g. where there's a
+ // space on the left hand side). This needs some particular care in the lookup
+ // which is usually word oriented.
+ TypoLookup db = TypoLookup.get(new TestLintClient(), "de", "DE"); //$NON-NLS-1$
+
+ // all zu->allzu
+
+ // Text handling
+ String t = "all zu";
+ assertNotNull(db.getTypos(t, 0, t.length()));
+ assertEquals("allzu", db.getTypos(t, 0, t.length()).get(1));
+
+ // Byte handling
+ byte[] text = "all zu".getBytes(Charsets.UTF_8);
+ assertNotNull(db.getTypos(text, 0, text.length));
+ assertEquals("allzu", db.getTypos(text, 0, text.length).get(1));
+
+ // Test automatically extending search beyond current word
+ text = "all zu".getBytes(Charsets.UTF_8);
+ assertNotNull(db.getTypos(text, 0, 3));
+ assertEquals("allzu", db.getTypos(text, 0, text.length).get(1));
+
+
+ text = ") all zu (".getBytes(Charsets.UTF_8);
+ assertNotNull(db.getTypos(text, 2, 8));
+ assertEquals("allzu", db.getTypos(text, 2, 8).get(1));
+
+ text = "am einem".getBytes(Charsets.UTF_8);
+ assertNotNull(db.getTypos(text, 0, text.length));
+ assertEquals("an einem", db.getTypos(text, 0, text.length).get(1));
+ }
+
+ public void testGlobbing() {
+ TypoLookup db = TypoLookup.get(new TestLintClient(), "de", null);
+
+ // Authorisierung*->Autorisierung*
+ String text = "Authorisierungscode";
+ byte[] bytes = text.getBytes(Charsets.UTF_8);
+
+ assertNotNull(db.getTypos(text, 0, text.length()));
+ assertEquals("Autorisierungscode", db.getTypos(text, 0, text.length()).get(1));
+ assertEquals(text, db.getTypos(text, 0, text.length()).get(0));
+
+ assertNotNull(db.getTypos(bytes, 0, bytes.length));
+ assertEquals("Autorisierungscode", db.getTypos(bytes, 0, bytes.length).get(1));
+
+ // befindet ein*->befindet sich ein*
+ text = "wo befindet eine ip";
+ assertEquals("befindet sich eine", db.getTypos(text, 3, 16).get(1));
+
+ // zurück ge*->zurückge*
+ text = "zurück gefoobaren";
+ bytes = text.getBytes(Charsets.UTF_8);
+ assertNotNull(db.getTypos(bytes, 0, bytes.length));
+ assertEquals("zurückgefoobaren", db.getTypos(bytes, 0, bytes.length).get(1));
+ }
+
+ public void testComparisons() throws Exception {
+ // Ensure that the two comparison methods agree
+
+ LintClient client = new TestLintClient();
+ for (String locale : new String[] { "de", "nb", "es", "en", "pt", "hu", "it", "tr" }) {
+ File f = client.findResource(String.format("tools/support/typos-%1$s.txt", locale));
+ assertTrue(locale, f != null && f.exists());
+
+ Set<String> typos = new HashSet<String>(2000);
+ List<String> lines = Files.readLines(f, Charsets.UTF_8);
+ for (int i = 0, n = lines.size(); i < n; i++) {
+ String line = lines.get(i);
+ if (line.isEmpty() || line.trim().startsWith("#")) { //$NON-NLS-1$
+ continue;
+ }
+
+ int index = line.indexOf(SEPARATOR);
+ if (index == -1) {
+ continue;
+ }
+ String typo = line.substring(0, index).trim();
+ typos.add(typo);
+ }
+
+ List<String> words = new ArrayList<String>(typos);
+
+ // Make sure that the two comparison methods agree on all the strings
+ // (which should be in a semi-random order now that they're in a set ordered
+ // by their hash codes)
+
+ String prevText = words.get(0) + '\000';
+ byte[] prevBytes = prevText.getBytes(Charsets.UTF_8);
+
+ for (int i = 1; i < words.size(); i++) {
+ String text = words.get(i) + '\000';;
+ byte[] bytes = text.getBytes(Charsets.UTF_8);
+
+ int textCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, text, 0,
+ text.length());
+ int byteCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, bytes, 0,
+ bytes.length);
+ assertEquals("Word " + text + " versus prev " + prevText + " at " + i,
+ Math.signum(textCompare), Math.signum(byteCompare));
+ }
+ }
+ }
+
+ public void testComparison1() throws Exception {
+ String prevText = "heraus gebracht\u0000";
+ byte[] prevBytes = prevText.getBytes(Charsets.UTF_8);
+
+ String text = "Päsident\u0000";
+ byte[] bytes = text.getBytes(Charsets.UTF_8);
+
+
+ int textCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, text, 0,
+ text.length());
+ int byteCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, bytes, 0,
+ bytes.length);
+ assertTrue(byteCompare < 0);
+ assertTrue(textCompare < 0);
+ assertEquals("Word " + text + " versus prev " + prevText,
+ Math.signum(textCompare), Math.signum(byteCompare));
+ }
+
+ public void testComparison2() throws Exception {
+ String prevText = "intepretation\u0000";
+ byte[] prevBytes = prevText.getBytes(Charsets.UTF_8);
+
+ String text = "Woudl\u0000";
+ byte[] bytes = text.getBytes(Charsets.UTF_8);
+
+ int textCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, text, 0, text.length());
+ int byteCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, bytes, 0, bytes.length);
+ assertTrue(byteCompare < 0);
+ assertTrue(textCompare < 0);
+ assertEquals("Word " + text + " versus prev " + prevText,
+ Math.signum(textCompare), Math.signum(byteCompare));
+
+ // Reverse capitalization and ensure that it's still the same
+ prevText = "Intepretation\u0000";
+ prevBytes = prevText.getBytes(Charsets.UTF_8);
+
+ text = "woudl\u0000";
+ bytes = text.getBytes(Charsets.UTF_8);
+
+ textCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, text, 0, text.length());
+ byteCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, bytes, 0, bytes.length);
+ assertTrue(byteCompare < 0);
+ assertTrue(textCompare < 0);
+ assertEquals("Word " + text + " versus prev " + prevText,
+ Math.signum(textCompare), Math.signum(byteCompare));
+ }
+
+ // Some dictionaries contain actual sentences regarding usage; these must be stripped out.
+ // They're just hardcoded here as we find them
+ private static final String[] sRemove = new String[] {
+ "- besser ganz darauf verzichten",
+ "oft fälschlich für \"angekündigt\"",
+ "hinausgehende* − insb. „darüber hinausgehende“",
+ " - besser ganz darauf verzichten",
+ "svw. bzw. so viel wie bzw. sprachverwandt"
+ };
+
+ private void validateDictionary(String locale) throws Exception {
+ // Check that all the typo files are well formed
+ LintClient client = new TestLintClient();
+ File f = client.findResource(String.format("tools/support/typos-%1$s.txt", locale));
+ assertTrue(locale, f != null && f.exists());
+
+ Set<String> typos = new HashSet<String>(2000);
+ List<Pattern> patterns = new ArrayList<Pattern>(100);
+
+ List<String> lines = Files.readLines(f, Charsets.UTF_8);
+ for (int i = 0, n = lines.size(); i < n; i++) {
+ String line = lines.get(i);
+ if (line.isEmpty() || line.trim().startsWith("#")) { //$NON-NLS-1$
+ continue;
+ }
+
+ assertTrue(msg(f, i, "Line should contain '->': %1$s", line),
+ line.contains(SEPARATOR));
+ int index = line.indexOf(SEPARATOR);
+ String typo = line.substring(0, index).trim();
+ String replacements = line.substring(index + SEPARATOR.length()).trim();
+
+ if (typo.contains("*") && !typo.endsWith("*")) {
+ fixDictionary(f);
+ fail(msg(f, i, "Globbing (*) not supported anywhere but at the tail: %1$s", line));
+ } else if (typo.contains("*") && !replacements.contains("*")) {
+ fail(msg(f, i, "No glob found in the replacements for %1$s", line));
+ }
+
+ if (replacements.indexOf(',') != -1) {
+ Set<String> seen = new HashSet<String>();
+ for (String s : Splitter.on(',').omitEmptyStrings().split(replacements)) {
+ if (seen.contains(s)) {
+ fixDictionary(f);
+ fail(msg(f, i, "For typo " + typo
+ + " there are repeated replacements (" + s + "): " + line));
+ }
+ }
+ }
+
+ assertTrue(msg(f, i, "Typo entry was empty: %1$s", line), !typo.isEmpty());
+ assertTrue(msg(f, i, "Typo replacements was empty: %1$s", line),
+ !replacements.isEmpty());
+
+ for (String blacklist : sRemove) {
+ if (replacements.contains(blacklist)) {
+ fail(msg(f, i, "Replacements for typo %1$s contain description: %2$s",
+ typo, replacements));
+ }
+ }
+ if (typo.equals("sólo") && locale.equals("es")) {
+ // sólo->solo
+ // This seems to trigger a lot of false positives
+ fail(msg(f, i, "Typo %1$s triggers a lot of false positives, should be omitted",
+ typo));
+ }
+ if (locale.equals("tr") && (typo.equals("hiç bir")|| typo.equals("öğe"))) {
+ // hiç bir->hiçbir
+ // öğe->öge
+ // According to a couple of native speakers these are not necessarily
+ // typos
+ fail(msg(f, i, "Typo %1$s triggers a lot of false positives, should be omitted",
+ typo));
+ }
+
+ if (typo.contains("*")) {
+ patterns.add(Pattern.compile(typo.replace("*", ".*")));
+ } else if (!patterns.isEmpty()) {
+ for (Pattern pattern : patterns) {
+ if (pattern.matcher(typo).matches()) {
+ fixDictionary(f);
+ fail(msg(f, i, "The typo " + typo + " matches an earlier glob: ignoring"));
+ continue;
+ }
+ }
+ }
+
+
+ if (typos.contains(typo)) {
+ fixDictionary(f);
+ fail(msg(f, i, "Typo appeared more than once on lhs: %1$s", typo));
+ }
+ typos.add(typo);
+ }
+
+ // Make sure it can be read in
+ TypoLookup db = TypoLookup.get(client, locale, null);
+ assertNotNull(db);
+ assertNull(db.getTypos("abcdefghijklmnopqrstuvxyz", 0, 25));
+ assertNull(db.getTypos("abcdefghijklmnopqrstuvxyz".getBytes(Charsets.UTF_8), 0, 25));
+ assertNotNull(db.getTypos("Andriod", 0, "Andriod".length()));
+ assertNotNull(db.getTypos("Andriod".getBytes(Charsets.UTF_8), 0, "Andriod".length()));
+ }
+
+ private void fixDictionary(File original) throws Exception {
+ File fixed = new File(original.getParentFile(), "fixed-" + original.getName());
+
+ Map<String, Integer> typos = new HashMap<String, Integer>(2000);
+ List<Pattern> patterns = new ArrayList<Pattern>(100);
+ List<String> lines = Files.readLines(original, Charsets.UTF_8);
+ List<String> output = new ArrayList<String>(lines.size());
+
+ wordLoop:
+ for (int i = 0, n = lines.size(); i < n; i++) {
+ String line = lines.get(i);
+ if (line.isEmpty() || line.trim().startsWith("#")) { //$NON-NLS-1$
+ output.add(line);
+ continue;
+ }
+
+ if (!line.contains(SEPARATOR)) {
+ System.err.println("Commented out line missing ->: " + line);
+ output.add("# " + line);
+ continue;
+ }
+ int index = line.indexOf(SEPARATOR);
+ String typo = line.substring(0, index).trim();
+ String replacements = line.substring(index + SEPARATOR.length()).trim();
+
+ if (typo.isEmpty()) {
+ System.err.println("Commented out line missing a typo on the lhs: " + line);
+ output.add("# " + line);
+ continue;
+ }
+ if (replacements.isEmpty()) {
+ System.err.println("Commented out line missing replacements on the rhs: " + line);
+ output.add("# " + line);
+ continue;
+ }
+
+ // Ensure that all the replacements are unique
+ if (replacements.indexOf(',') != -1) {
+ Set<String> seen = new HashSet<String>();
+ List<String> out = new ArrayList<String>();
+ boolean rewrite = false;
+ for (String s : Splitter.on(',').omitEmptyStrings().split(replacements)) {
+ if (seen.contains(s)) {
+ System.err.println("For typo " + typo
+ + " there are repeated replacements (" + s + "): " + line);
+ rewrite = true;
+ }
+ seen.add(s);
+ out.add(s);
+ }
+ if (rewrite) {
+ StringBuilder sb = new StringBuilder();
+ for (String s : out) {
+ if (sb.length() > 0) {
+ sb.append(",");
+ }
+ sb.append(s);
+ }
+ replacements = sb.toString();
+ line = typo + SEPARATOR + replacements;
+ }
+ }
+
+ if (typo.contains("*")) {
+ if (!typo.endsWith("*")) {
+ // Globbing not supported anywhere but the end
+ // Drop the whole word
+ System.err.println("Skipping typo " + typo
+ + " because globbing is only supported at the end of the word");
+ continue;
+ }
+ patterns.add(Pattern.compile(typo.replace("*", ".*")));
+ } else if (replacements.contains("*")) {
+ System.err.println("Skipping typo " + typo + " because unexpected " +
+ "globbing character found in replacements: "
+ + replacements);
+ continue;
+ } else if (!patterns.isEmpty()) {
+ for (Pattern pattern : patterns) {
+ if (pattern.matcher(typo).matches()) {
+ System.err.println("The typo " + typo
+ + " matches an earlier glob: ignoring");
+ continue wordLoop;
+ }
+ }
+ }
+
+ // TODO: Strip whitespace around ->, prefix of # etc such that reading in
+ // the databases needs to do less work at runtime
+
+ if (typos.containsKey(typo)) {
+ int l = typos.get(typo);
+ String prev = output.get(l);
+ assertTrue(prev.startsWith(typo));
+ // Append new replacements and put back into the list
+ // (unless they're already listed as replacements)
+ Set<String> seen = new HashSet<String>();
+ for (String s : Splitter.on(',').split(prev.substring(prev.indexOf(SEPARATOR)
+ + 2))) {
+ seen.add(s);
+ }
+ for (String s : Splitter.on(',').omitEmptyStrings().split(replacements)) {
+ if (!seen.contains(s)) {
+ prev = prev + "," + s;
+ }
+ seen.add(s);
+ }
+ output.set(l, prev);
+ } else {
+ typos.put(typo, output.size());
+ output.add(line);
+ }
+ }
+
+ Writer writer = new BufferedWriter(new FileWriter(fixed));
+ for (String line : output) {
+ writer.write(line);
+ writer.write('\n');
+ }
+ writer.close();
+
+ System.err.println("==> Wrote fixed typo file to " + fixed.getPath());
+ }
+
+ private static String msg(File file, int line, String message, Object... args) {
+ return file.getName() + ':' + Integer.toString(line + 1) + ':' + ' ' +
+ String.format(message, args);
+ }
+
+ @Override
+ protected Detector getDetector() {
+ fail("This is not used in the TypoLookupTest");
+ return null;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/TypographyDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/TypographyDetectorTest.java
new file mode 100644
index 0000000..16d0107
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/TypographyDetectorTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import static com.android.tools.lint.checks.TypographyDetector.FRACTION_PATTERN;
+import static com.android.tools.lint.checks.TypographyDetector.GRAVE_QUOTATION;
+import static com.android.tools.lint.checks.TypographyDetector.HYPHEN_RANGE_PATTERN;
+import static com.android.tools.lint.checks.TypographyDetector.SINGLE_QUOTE;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class TypographyDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new TypographyDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/values/typography.xml:17: Warning: Replace \"-\" with an \"en dash\" character (–, &#8211;) ? [TypographyDashes]\n" +
+ " <string name=\"ndash\">For ages 3-5</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:18: Warning: Replace \"-\" with an \"en dash\" character (–, &#8211;) ? [TypographyDashes]\n" +
+ " <string name=\"ndash2\">Copyright 2007 - 2011</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:20: Warning: Replace \"--\" with an \"em dash\" character (—, &#8212;) ? [TypographyDashes]\n" +
+ " <string name=\"mdash\">Not found -- please try again</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:24: Warning: Replace \"-\" with an \"en dash\" character (–, &#8211;) ? [TypographyDashes]\n" +
+ " <item>Ages 3-5</item>\n" +
+ " ^\n" +
+ "res/values/typography.xml:15: Warning: Replace \"...\" with ellipsis character (…, &#8230;) ? [TypographyEllipsis]\n" +
+ " <string name=\"ellipsis\">40 times...</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:12: Warning: Use fraction character ½ (&#189;) instead of 1/2 ? [TypographyFractions]\n" +
+ " <string name=\"fraction1\">5 1/2 times</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:13: Warning: Use fraction character ¼ (&#188;) instead of 1/4 ? [TypographyFractions]\n" +
+ " <string name=\"fraction4\">1/4 times</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:25: Warning: Use fraction character ½ (&#189;) instead of 1/2 ? [TypographyFractions]\n" +
+ " <item>Age 5 1/2</item>\n" +
+ " ^\n" +
+ "res/values/typography.xml:3: Warning: Replace straight quotes ('') with directional quotes (‘’, &#8216; and &#8217;) ? [TypographyQuotes]\n" +
+ " <string name=\"home_title\">Home 'Sample'</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:5: Warning: Replace straight quotes (\") with directional quotes (“”, &#8220; and &#8221;) ? [TypographyQuotes]\n" +
+ " <string name=\"show_all_apps2\">Show \"All\"</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:6: Warning: Replace straight quotes (\") with directional quotes (“”, &#8220; and &#8221;) ? [TypographyQuotes]\n" +
+ " <string name=\"escaped\">Skip \\\"All\\\"</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:7: Warning: Replace apostrophe (') with typographic apostrophe (’, &#8217;) ? [TypographyQuotes]\n" +
+ " <string name=\"single\">Android's</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:9: Warning: Replace apostrophe (') with typographic apostrophe (’, &#8217;) ? [TypographyQuotes]\n" +
+ " <string name=\"badquotes1\">`First'</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:10: Warning: Avoid quoting with grave accents; use apostrophes or better yet directional quotes instead [TypographyQuotes]\n" +
+ " <string name=\"badquotes2\">``second''</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:11: Warning: Replace straight quotes ('') with directional quotes (‘’, &#8216; and &#8217;) ? [TypographyQuotes]\n" +
+ " <string name=\"notbadquotes\">Type Option-` then 'Escape'</string>\n" +
+ " ^\n" +
+ "res/values/typography.xml:8: Warning: Replace (c) with copyright symbol © (&#169;) ? [TypographyOther]\n" +
+ " <string name=\"copyright\">(c) 2011</string>\n" +
+ " ^\n" +
+ "0 errors, 16 warnings\n" +
+ "",
+
+ lintProject("res/values/typography.xml"));
+ }
+
+ public void testSingleQuotesRange() {
+ assertTrue(SINGLE_QUOTE.matcher("Foo: 'bar'").matches());
+ assertTrue(SINGLE_QUOTE.matcher("'Foo': bar").matches());
+ assertTrue(SINGLE_QUOTE.matcher("\"'foo'\"").matches());
+ assertTrue(SINGLE_QUOTE.matcher("\"'foo bar'\"").matches());
+
+ assertFalse(SINGLE_QUOTE.matcher("foo bar'").matches());
+ assertFalse(SINGLE_QUOTE.matcher("Mind your P's and Q's").matches());
+
+ // This isn't asserted by the regexp: checked independently in
+ // the detector. The goal here is to assert that we need to
+ // have some text on either side of the quotes.
+ //assertFalse(SINGLE_QUOTE.matcher("'foo bar'").matches());
+ }
+
+ public void testGraveRegexp() {
+ assertTrue(GRAVE_QUOTATION.matcher("`a'").matches());
+ assertTrue(GRAVE_QUOTATION.matcher(" `a' ").matches());
+ assertTrue(GRAVE_QUOTATION.matcher(" ``a'' ").matches());
+ assertFalse(GRAVE_QUOTATION.matcher("`a''").matches());
+ }
+
+ public void testFractionRegexp() {
+ assertTrue(FRACTION_PATTERN.matcher("fraction 1/2.").matches());
+ assertTrue(FRACTION_PATTERN.matcher("1/2").matches());
+ assertTrue(FRACTION_PATTERN.matcher("1/3").matches());
+ assertTrue(FRACTION_PATTERN.matcher("1/4").matches());
+ assertTrue(FRACTION_PATTERN.matcher("3/4").matches());
+ assertTrue(FRACTION_PATTERN.matcher("1 / 2").matches());
+ assertTrue(FRACTION_PATTERN.matcher("1 / 3").matches());
+ assertTrue(FRACTION_PATTERN.matcher("1 / 4").matches());
+ assertTrue(FRACTION_PATTERN.matcher("3 / 4").matches());
+
+ assertFalse(FRACTION_PATTERN.matcher("3 // 4").matches());
+ assertFalse(FRACTION_PATTERN.matcher("11 / 2").matches());
+ assertFalse(FRACTION_PATTERN.matcher("1 / 22").matches());
+ }
+
+ public void testNDashRegexp() {
+ assertTrue(HYPHEN_RANGE_PATTERN.matcher("3-4").matches());
+ assertTrue(HYPHEN_RANGE_PATTERN.matcher("13- 14").matches());
+ assertTrue(HYPHEN_RANGE_PATTERN.matcher("13 - 14").matches());
+ assertTrue(HYPHEN_RANGE_PATTERN.matcher("The range is 13 - 14").matches());
+ assertTrue(HYPHEN_RANGE_PATTERN.matcher("13 - 14.").matches());
+
+ assertFalse(HYPHEN_RANGE_PATTERN.matcher("13 - x").matches());
+ assertFalse(HYPHEN_RANGE_PATTERN.matcher("x - 14").matches());
+ assertFalse(HYPHEN_RANGE_PATTERN.matcher("x-y").matches());
+ assertFalse(HYPHEN_RANGE_PATTERN.matcher("-y").matches());
+ assertFalse(HYPHEN_RANGE_PATTERN.matcher("x-").matches());
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/UnusedResourceDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/UnusedResourceDetectorTest.java
new file mode 100644
index 0000000..9113e79
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/UnusedResourceDetectorTest.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Issue;
+
+import java.io.File;
+import java.util.Arrays;
+
+@SuppressWarnings("javadoc")
+public class UnusedResourceDetectorTest extends AbstractCheckTest {
+ private boolean mEnableIds = false;
+
+ @Override
+ protected Detector getDetector() {
+ return new UnusedResourceDetector();
+ }
+
+ @Override
+ protected boolean isEnabled(Issue issue) {
+ if (issue == UnusedResourceDetector.ISSUE_IDS) {
+ return mEnableIds;
+ } else {
+ return true;
+ }
+ }
+
+ public void testUnused() throws Exception {
+ mEnableIds = false;
+ assertEquals(
+ "res/layout/accessibility.xml: Warning: The resource R.layout.accessibility appears to be unused [UnusedResources]\n" +
+ "res/layout/main.xml: Warning: The resource R.layout.main appears to be unused [UnusedResources]\n" +
+ "res/layout/other.xml: Warning: The resource R.layout.other appears to be unused [UnusedResources]\n" +
+ "res/values/strings2.xml:3: Warning: The resource R.string.hello appears to be unused [UnusedResources]\n" +
+ " <string name=\"hello\">Hello</string>\n" +
+ " ~~~~~~~~~~~~\n" +
+ "0 errors, 4 warnings\n" +
+ "",
+
+ lintProject(
+ "res/values/strings2.xml",
+ "res/layout/layout1.xml=>res/layout/main.xml",
+ "res/layout/layout1.xml=>res/layout/other.xml",
+
+ // Rename .txt files to .java
+ "src/my/pkg/Test.java.txt=>src/my/pkg/Test.java",
+ "gen/my/pkg/R.java.txt=>gen/my/pkg/R.java",
+ "AndroidManifest.xml",
+ "res/layout/accessibility.xml"));
+ }
+
+ public void testUnusedIds() throws Exception {
+ mEnableIds = true;
+
+ assertEquals(
+ "res/layout/accessibility.xml: Warning: The resource R.layout.accessibility appears to be unused [UnusedResources]\n" +
+ "Warning: The resource R.layout.main appears to be unused [UnusedResources]\n" +
+ "Warning: The resource R.layout.other appears to be unused [UnusedResources]\n" +
+ "Warning: The resource R.string.hello appears to be unused [UnusedResources]\n" +
+ "Warning: The resource R.id.imageView1 appears to be unused [UnusedIds]\n" +
+ "Warning: The resource R.id.include1 appears to be unused [UnusedIds]\n" +
+ "Warning: The resource R.id.linearLayout2 appears to be unused [UnusedIds]\n" +
+ "res/layout/accessibility.xml:2: Warning: The resource R.id.newlinear appears to be unused [UnusedIds]\n" +
+ "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\" android:id=\"@+id/newlinear\" android:orientation=\"vertical\" android:layout_width=\"match_parent\" android:layout_height=\"match_parent\">\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/accessibility.xml:3: Warning: The resource R.id.button1 appears to be unused [UnusedIds]\n" +
+ " <Button android:text=\"Button\" android:id=\"@+id/button1\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\"></Button>\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/accessibility.xml:4: Warning: The resource R.id.android_logo appears to be unused [UnusedIds]\n" +
+ " <ImageView android:id=\"@+id/android_logo\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:src=\"@drawable/android_button\" android:focusable=\"false\" android:clickable=\"false\" android:layout_weight=\"1.0\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/accessibility.xml:5: Warning: The resource R.id.android_logo2 appears to be unused [UnusedIds]\n" +
+ " <ImageButton android:importantForAccessibility=\"yes\" android:id=\"@+id/android_logo2\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:src=\"@drawable/android_button\" android:focusable=\"false\" android:clickable=\"false\" android:layout_weight=\"1.0\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 11 warnings\n" +
+ "",
+
+ lintProject(
+ // Rename .txt files to .java
+ "src/my/pkg/Test.java.txt=>src/my/pkg/Test.java",
+ "gen/my/pkg/R.java.txt=>gen/my/pkg/R.java",
+ "AndroidManifest.xml",
+ "res/layout/accessibility.xml"));
+ }
+
+ public void testArrayReference() throws Exception {
+ assertEquals(
+ "res/values/arrayusage.xml:3: Warning: The resource R.array.my_array appears to be unused [UnusedResources]\n" +
+ "<string-array name=\"my_array\">\n" +
+ " ~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "AndroidManifest.xml",
+ "res/values/arrayusage.xml"));
+ }
+
+ public void testAttrs() throws Exception {
+ assertEquals(
+ "res/layout/customattrlayout.xml: Warning: The resource R.layout.customattrlayout appears to be unused [UnusedResources]\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "res/values/customattr.xml",
+ "res/layout/customattrlayout.xml",
+ "unusedR.java.txt=>gen/my/pkg/R.java",
+ "AndroidManifest.xml"));
+ }
+
+ public void testMultiProjectIgnoreLibraries() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ // Master project
+ "multiproject/main-manifest.xml=>AndroidManifest.xml",
+ "multiproject/main.properties=>project.properties",
+ "multiproject/MainCode.java.txt=>src/foo/main/MainCode.java",
+
+ // Library project
+ "multiproject/library-manifest.xml=>../LibraryProject/AndroidManifest.xml",
+ "multiproject/library.properties=>../LibraryProject/project.properties",
+ "multiproject/LibraryCode.java.txt=>../LibraryProject/src/foo/library/LibraryCode.java",
+ "multiproject/strings.xml=>../LibraryProject/res/values/strings.xml"
+ ));
+ }
+
+ public void testMultiProject() throws Exception {
+ File master = getProjectDir("MasterProject",
+ // Master project
+ "multiproject/main-manifest.xml=>AndroidManifest.xml",
+ "multiproject/main.properties=>project.properties",
+ "multiproject/MainCode.java.txt=>src/foo/main/MainCode.java"
+ );
+ File library = getProjectDir("LibraryProject",
+ // Library project
+ "multiproject/library-manifest.xml=>AndroidManifest.xml",
+ "multiproject/library.properties=>project.properties",
+ "multiproject/LibraryCode.java.txt=>src/foo/library/LibraryCode.java",
+ "multiproject/strings.xml=>res/values/strings.xml"
+ );
+ assertEquals(
+ // string1 is defined and used in the library project
+ // string2 is defined in the library project and used in the master project
+ // string3 is defined in the library project and not used anywhere
+ "/TESTROOT/LibraryProject/res/values/strings.xml:7: Warning: The resource R.string.string3 appears to be unused [UnusedResources]\n" +
+ " <string name=\"string3\">String 3</string>\n" +
+ " ~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n",
+
+ checkLint(Arrays.asList(master, library)));
+ }
+
+ public void testFqcnReference() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/layout/layout1.xml=>res/layout/main.xml",
+ "src/test/pkg/UnusedReference.java.txt=>src/test/pkg/UnusedReference.java",
+ "AndroidManifest.xml"));
+ }
+
+ public void testIgnoreXmlDrawable() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/drawable/ic_menu_help.xml",
+ "gen/my/pkg/R2.java.txt=>gen/my/pkg/R.java"
+ ));
+ }
+
+ public void testPlurals() throws Exception {
+ assertEquals(
+ "res/values/plurals.xml:3: Warning: The resource R.plurals.my_plural appears to be unused [UnusedResources]\n" +
+ " <plurals name=\"my_plural\">\n" +
+ " ~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "res/values/strings4.xml",
+ "res/values/plurals.xml",
+ "AndroidManifest.xml"));
+ }
+
+ public void testNoMerging() throws Exception {
+ // http://code.google.com/p/android/issues/detail?id=36952
+
+ File master = getProjectDir("MasterProject",
+ // Master project
+ "multiproject/main-manifest.xml=>AndroidManifest.xml",
+ "multiproject/main.properties=>project.properties",
+ "multiproject/MainCode.java.txt=>src/foo/main/MainCode.java"
+ );
+ File library = getProjectDir("LibraryProject",
+ // Library project
+ "multiproject/library-manifest.xml=>AndroidManifest.xml",
+ "multiproject/library.properties=>project.properties",
+ "multiproject/LibraryCode.java.txt=>src/foo/library/LibraryCode.java",
+ "multiproject/strings.xml=>res/values/strings.xml"
+ );
+ assertEquals(
+ // The strings are all referenced in the library project's manifest file
+ // which in this project is merged in
+ "/TESTROOT/LibraryProject/res/values/strings.xml:7: Warning: The resource R.string.string3 appears to be unused [UnusedResources]\n" +
+ " <string name=\"string3\">String 3</string>\n" +
+ " ~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n",
+
+ checkLint(Arrays.asList(master, library)));
+ }
+
+ public void testLibraryMerging() throws Exception {
+ // http://code.google.com/p/android/issues/detail?id=36952
+ File master = getProjectDir("MasterProject",
+ // Master project
+ "multiproject/main-manifest.xml=>AndroidManifest.xml",
+ "multiproject/main-merge.properties=>project.properties",
+ "multiproject/MainCode.java.txt=>src/foo/main/MainCode.java"
+ );
+ File library = getProjectDir("LibraryProject",
+ // Library project
+ "multiproject/library-manifest.xml=>AndroidManifest.xml",
+ "multiproject/library.properties=>project.properties",
+ "multiproject/LibraryCode.java.txt=>src/foo/library/LibraryCode.java",
+ "multiproject/strings.xml=>res/values/strings.xml"
+ );
+ assertEquals(
+ // The strings are all referenced in the library project's manifest file
+ // which in this project is merged in
+ "No warnings.",
+
+ checkLint(Arrays.asList(master, library)));
+ }
+
+ public void testCornerCase() throws Exception {
+ // See http://code.google.com/p/projectlombok/issues/detail?id=415
+ mEnableIds = true;
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/layout/accessibility.xml",
+ "src/test/pkg/Foo.java.txt=>src/test/pkg/Foo.java",
+ "AndroidManifest.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java
new file mode 100644
index 0000000..146ff6f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class UseCompoundDrawableDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new UseCompoundDrawableDetector();
+ }
+
+ public void testCompound() throws Exception {
+ assertEquals(
+ "res/layout/compound.xml:3: Warning: This tag and its children can be replaced by one <TextView/> and a compound drawable [UseCompoundDrawables]\n" +
+ "<LinearLayout\n" +
+ "^\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintFiles("res/layout/compound.xml"));
+ }
+
+ public void testCompound2() throws Exception {
+ // Ignore layouts that set a custom background
+ assertEquals(
+ "No warnings.",
+ lintFiles("res/layout/compound2.xml"));
+ }
+
+ public void testCompound3() throws Exception {
+ // Ignore layouts that set an image scale type
+ assertEquals(
+ "No warnings.",
+ lintFiles("res/layout/compound3.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/UselessViewDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/UselessViewDetectorTest.java
new file mode 100644
index 0000000..c34b987
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/UselessViewDetectorTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class UselessViewDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new UselessViewDetector();
+ }
+
+ public void testUseless() throws Exception {
+ assertEquals(
+ "res/layout/useless.xml:85: Warning: This FrameLayout view is useless (no children, no background, no id, no style) [UselessLeaf]\n" +
+ " <FrameLayout\n" +
+ " ^\n" +
+ "res/layout/useless.xml:13: Warning: This LinearLayout layout or its FrameLayout parent is useless [UselessParent]\n" +
+ " <LinearLayout\n" +
+ " ^\n" +
+ "res/layout/useless.xml:47: Warning: This LinearLayout layout or its FrameLayout parent is useless; transfer the background attribute to the other view [UselessParent]\n" +
+ " <LinearLayout\n" +
+ " ^\n" +
+ "res/layout/useless.xml:65: Warning: This LinearLayout layout or its FrameLayout parent is useless; transfer the background attribute to the other view [UselessParent]\n" +
+ " <LinearLayout\n" +
+ " ^\n" +
+ "0 errors, 4 warnings\n" +
+ "",
+ lintFiles("res/layout/useless.xml"));
+ }
+
+ public void testTabHost() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles("res/layout/useless2.xml"));
+ }
+
+ public void testStyleAttribute() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles("res/layout/useless3.xml"));
+ }
+
+ public void testUselessLeafRoot() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles("res/layout/breadcrumbs_in_fragment.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/Utf8DetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/Utf8DetectorTest.java
new file mode 100644
index 0000000..d1a118d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/Utf8DetectorTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class Utf8DetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new Utf8Detector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/layout/encoding.xml:1: Warning: iso-latin-1: Not using UTF-8 as the file encoding. This can lead to subtle bugs with non-ascii characters [EnforceUTF8]\n" +
+ "<?xml version=\"1.0\" encoding=\"iso-latin-1\"?>\n" +
+ " ~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ lintProject("res/layout/encoding.xml"));
+ }
+
+ public void testWithR() throws Exception {
+ assertEquals(
+ "res/layout/encoding2.xml:1: Warning: iso-latin-1: Not using UTF-8 as the file encoding. This can lead to subtle bugs with non-ascii characters [EnforceUTF8]\n" +
+ "<?xml version=\"1.0\" encoding=\"iso-latin-1\"?>\n" +
+ " ~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+ // encoding2.xml = encoding.xml but with \n => \r
+ lintProject("res/layout/encoding2.xml"));
+ }
+
+ public void testNegative() throws Exception {
+ // Make sure we don't get warnings for a correct file
+ assertEquals(
+ "No warnings.",
+ lintProject("res/layout/layout1.xml"));
+ }
+
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ViewConstructorDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ViewConstructorDetectorTest.java
new file mode 100644
index 0000000..5517646
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ViewConstructorDetectorTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class ViewConstructorDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ViewConstructorDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/bytecode/CustomView1.java: Warning: Custom view test/pkg/CustomView1 is missing constructor used by tools: (Context) or (Context,AttributeSet) or (Context,AttributeSet,int) [ViewConstructor]\n" +
+ "src/test/bytecode/CustomView2.java: Warning: Custom view test/pkg/CustomView2 is missing constructor used by tools: (Context) or (Context,AttributeSet) or (Context,AttributeSet,int) [ViewConstructor]\n" +
+ "0 errors, 2 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "bytecode/CustomView1.java.txt=>src/test/bytecode/CustomView1.java",
+ "bytecode/CustomView2.java.txt=>src/test/bytecode/CustomView2.java",
+ "bytecode/CustomView3.java.txt=>src/test/bytecode/CustomView3.java",
+ "bytecode/CustomView1.class.data=>bin/classes/test/bytecode/CustomView1.class",
+ "bytecode/CustomView2.class.data=>bin/classes/test/bytecode/CustomView2.class",
+ "bytecode/CustomView3.class.data=>bin/classes/test/bytecode/CustomView3.class"
+ ));
+ }
+
+ public void testInheritLocal() throws Exception {
+ assertEquals(
+ "src/test/pkg/CustomViewTest.java: Warning: Custom view test/pkg/CustomViewTest is missing constructor used by tools: (Context) or (Context,AttributeSet) or (Context,AttributeSet,int) [ViewConstructor]\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "apicheck/Intermediate.java.txt=>src/test/pkg/Intermediate.java.txt",
+ "src/test/pkg/CustomViewTest.java.txt=>src/test/pkg/CustomViewTest.java",
+ "bytecode/CustomViewTest.class.data=>bin/classes/test/pkg/CustomViewTest.class",
+ "apicheck/Intermediate.class.data=>bin/classes/test/pkg/Intermediate.class",
+ "apicheck/Intermediate$IntermediateCustomV.class.data=>" +
+ "bin/classes/test/pkg/Intermediate$IntermediateCustomV.class"
+ ));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ViewTagDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ViewTagDetectorTest.java
new file mode 100644
index 0000000..8d9e2d5
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ViewTagDetectorTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class ViewTagDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ViewTagDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/ViewTagTest.java:21: Warning: Avoid setting views as values for setTag: Can lead to memory leaks in versions older than Android 4.0 [ViewTag]\n" +
+ " view.setTag(android.R.id.button1, group); // ERROR\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/ViewTagTest.java:22: Warning: Avoid setting views as values for setTag: Can lead to memory leaks in versions older than Android 4.0 [ViewTag]\n" +
+ " view.setTag(android.R.id.icon, view.findViewById(android.R.id.icon)); // ERROR\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/ViewTagTest.java:23: Warning: Avoid setting cursors as values for setTag: Can lead to memory leaks in versions older than Android 4.0 [ViewTag]\n" +
+ " view.setTag(android.R.id.icon1, cursor1); // ERROR\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/ViewTagTest.java:24: Warning: Avoid setting cursors as values for setTag: Can lead to memory leaks in versions older than Android 4.0 [ViewTag]\n" +
+ " view.setTag(android.R.id.icon2, cursor2); // ERROR\n" +
+ " ~~~~~~\n" +
+ "src/test/pkg/ViewTagTest.java:25: Warning: Avoid setting view holders as values for setTag: Can lead to memory leaks in versions older than Android 4.0 [ViewTag]\n" +
+ " view.setTag(android.R.id.copy, new MyViewHolder()); // ERROR\n" +
+ " ~~~~~~\n" +
+ "0 errors, 5 warnings\n",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "res/layout/onclick.xml=>res/layout/onclick.xml",
+ "bytecode/ViewTagTest.java.txt=>src/test/pkg/ViewTagTest.java",
+ "bytecode/ViewTagTest.class.data=>bin/classes/test/pkg/ViewTagTest.class"
+ ));
+ }
+
+ public void testICS() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/layout/onclick.xml=>res/layout/onclick.xml",
+ "bytecode/ViewTagTest.java.txt=>src/test/pkg/ViewTagTest.java",
+ "bytecode/ViewTagTest.class.data=>bin/classes/test/pkg/ViewTagTest.class"
+ ));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ViewTypeDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ViewTypeDetectorTest.java
new file mode 100644
index 0000000..cf38197
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ViewTypeDetectorTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class ViewTypeDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ViewTypeDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/WrongCastActivity.java:13: Error: Unexpected cast to ToggleButton: layout tag was Button [WrongViewCast]\n" +
+ " ToggleButton toggleButton = (ToggleButton) findViewById(R.id.button);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject(
+ "res/layout/casts.xml",
+ "src/test/pkg/WrongCastActivity.java.txt=>src/test/pkg/WrongCastActivity.java"
+ ));
+ }
+
+ public void test2() throws Exception {
+ assertEquals(
+ "src/test/pkg/WrongCastActivity.java:13: Error: Unexpected cast to ToggleButton: layout tag was Button|RadioButton [WrongViewCast]\n" +
+ " ToggleButton toggleButton = (ToggleButton) findViewById(R.id.button);\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject(
+ "res/layout/casts.xml",
+ "res/layout/casts3.xml",
+ "src/test/pkg/WrongCastActivity.java.txt=>src/test/pkg/WrongCastActivity.java"
+ ));
+ }
+
+ public void test3() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/layout/casts.xml",
+ "res/layout/casts4.xml",
+ "src/test/pkg/WrongCastActivity.java.txt=>src/test/pkg/WrongCastActivity.java"
+ ));
+ }
+
+ public void test27441() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/layout/casts2.xml",
+ "src/test/pkg/WrongCastActivity2.java.txt=>src/test/pkg/WrongCastActivity2.java"
+ ));
+ }
+
+ public void testCheckable() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "res/layout/casts2.xml",
+ "src/test/pkg/WrongCastActivity3.java.txt=>src/test/pkg/WrongCastActivity3.java"
+ ));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/WakelockDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/WakelockDetectorTest.java
new file mode 100644
index 0000000..f136dd9
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/WakelockDetectorTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class WakelockDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new WakelockDetector();
+ }
+
+ public void test1() throws Exception {
+ assertEquals(
+ "src/test/pkg/WakelockActivity1.java:15: Warning: Found a wakelock acquire() but no release() calls anywhere [Wakelock]\n" +
+ " mWakeLock.acquire(); // Never released\n" +
+ " ~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "res/layout/onclick.xml=>res/layout/onclick.xml",
+ "bytecode/WakelockActivity1.java.txt=>src/test/pkg/WakelockActivity1.java",
+ "bytecode/WakelockActivity1.class.data=>bin/classes/test/pkg/WakelockActivity1.class"
+ ));
+ }
+
+ public void test2() throws Exception {
+ assertEquals(
+ "src/test/pkg/WakelockActivity2.java:13: Warning: Wakelocks should be released in onPause, not onDestroy [Wakelock]\n" +
+ " mWakeLock.release(); // Should be done in onPause instead\n" +
+ " ~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "res/layout/onclick.xml=>res/layout/onclick.xml",
+ "bytecode/WakelockActivity2.java.txt=>src/test/pkg/WakelockActivity2.java",
+ "bytecode/WakelockActivity2.class.data=>bin/classes/test/pkg/WakelockActivity2.class"
+ ));
+ }
+
+ public void test3() throws Exception {
+ assertEquals(
+ "src/test/pkg/WakelockActivity3.java:13: Warning: The release() call is not always reached [Wakelock]\n" +
+ " lock.release(); // Should be in finally block\n" +
+ " ~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "res/layout/onclick.xml=>res/layout/onclick.xml",
+ "bytecode/WakelockActivity3.java.txt=>src/test/pkg/WakelockActivity3.java",
+ "bytecode/WakelockActivity3.class.data=>bin/classes/test/pkg/WakelockActivity3.class"
+ ));
+ }
+
+ public void test4() throws Exception {
+ assertEquals(
+ "src/test/pkg/WakelockActivity4.java:10: Warning: The release() call is not always reached [Wakelock]\n" +
+ " getLock().release(); // Should be in finally block\n" +
+ " ~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "res/layout/onclick.xml=>res/layout/onclick.xml",
+ "bytecode/WakelockActivity4.java.txt=>src/test/pkg/WakelockActivity4.java",
+ "bytecode/WakelockActivity4.class.data=>bin/classes/test/pkg/WakelockActivity4.class"
+ ));
+ }
+
+ public void test5() throws Exception {
+ assertEquals(
+ "src/test/pkg/WakelockActivity5.java:13: Warning: The release() call is not always reached [Wakelock]\n" +
+ " lock.release(); // Should be in finally block\n" +
+ " ~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "res/layout/onclick.xml=>res/layout/onclick.xml",
+ "bytecode/WakelockActivity5.java.txt=>src/test/pkg/WakelockActivity5.java",
+ "bytecode/WakelockActivity5.class.data=>bin/classes/test/pkg/WakelockActivity5.class"
+ ));
+ }
+
+ public void test6() throws Exception {
+ assertEquals(
+ "src/test/pkg/WakelockActivity6.java:19: Warning: The release() call is not always reached [Wakelock]\n" +
+ " lock.release(); // Wrong\n" +
+ " ~~~~~~~\n" +
+ "src/test/pkg/WakelockActivity6.java:28: Warning: The release() call is not always reached [Wakelock]\n" +
+ " lock.release(); // Wrong\n" +
+ " ~~~~~~~\n" +
+ "src/test/pkg/WakelockActivity6.java:65: Warning: The release() call is not always reached [Wakelock]\n" +
+ " lock.release(); // Wrong\n" +
+ " ~~~~~~~\n" +
+ "0 errors, 3 warnings\n" +
+ "",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "res/layout/onclick.xml=>res/layout/onclick.xml",
+ "bytecode/WakelockActivity6.java.txt=>src/test/pkg/WakelockActivity6.java",
+ "bytecode/WakelockActivity6.class.data=>bin/classes/test/pkg/WakelockActivity6.class"
+ ));
+ }
+
+ public void test7() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "res/layout/onclick.xml=>res/layout/onclick.xml",
+ "bytecode/WakelockActivity7.java.txt=>src/test/pkg/WakelockActivity7.java",
+ "bytecode/WakelockActivity7.class.data=>bin/classes/test/pkg/WakelockActivity7.class"
+ ));
+ }
+
+ public void test8() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/.classpath=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "bytecode/WakelockActivity8.java.txt=>src/test/pkg/WakelockActivity8.java",
+ "bytecode/WakelockActivity8.class.data=>bin/classes/test/pkg/WakelockActivity8.class"
+ ));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/WrongIdDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/WrongIdDetectorTest.java
new file mode 100644
index 0000000..b3fd203
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/WrongIdDetectorTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class WrongIdDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new WrongIdDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/layout/layout1.xml:14: Error: The id \"button5\" is not defined anywhere. Did you mean one of {button1, button2, button3, button4} ? [UnknownId]\n" +
+ " android:layout_alignBottom=\"@+id/button5\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/layout1.xml:17: Error: The id \"my_id3\" is not defined anywhere. Did you mean my_id2 ? [UnknownId]\n" +
+ " android:layout_alignRight=\"@+id/my_id3\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/layout1.xml:18: Error: The id \"my_id1\" is defined but not assigned to any views. Did you mean my_id2 ? [UnknownId]\n" +
+ " android:layout_alignTop=\"@+id/my_id1\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/layout1.xml:15: Warning: The id \"my_id2\" is not referring to any views in this layout [UnknownIdInLayout]\n" +
+ " android:layout_alignLeft=\"@+id/my_id2\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "3 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "wrongid/layout1.xml=>res/layout/layout1.xml",
+ "wrongid/layout2.xml=>res/layout/layout2.xml",
+ "wrongid/ids.xml=>res/values/ids.xml"
+ ));
+ }
+
+ public void testSingleFile() throws Exception {
+ assertEquals(
+ "res/layout/layout1.xml:14: Warning: The id \"button5\" is not referring to any views in this layout [UnknownIdInLayout]\n" +
+ " android:layout_alignBottom=\"@+id/button5\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/layout1.xml:15: Warning: The id \"my_id2\" is not referring to any views in this layout [UnknownIdInLayout]\n" +
+ " android:layout_alignLeft=\"@+id/my_id2\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/layout1.xml:17: Warning: The id \"my_id3\" is not referring to any views in this layout [UnknownIdInLayout]\n" +
+ " android:layout_alignRight=\"@+id/my_id3\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "res/layout/layout1.xml:18: Warning: The id \"my_id1\" is not referring to any views in this layout [UnknownIdInLayout]\n" +
+ " android:layout_alignTop=\"@+id/my_id1\"\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 4 warnings\n" +
+ "",
+
+ lintFiles("wrongid/layout1.xml=>res/layout/layout1.xml"));
+ }
+
+ public void testSuppressed() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "wrongid/ignorelayout1.xml=>res/layout/layout1.xml",
+ "wrongid/layout2.xml=>res/layout/layout2.xml",
+ "wrongid/ids.xml=>res/values/ids.xml"
+ ));
+ }
+
+ public void testSuppressedSingleFile() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles("wrongid/ignorelayout1.xml=>res/layout/layout1.xml"));
+ }
+
+ public void testNewIdPrefix() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles("res/layout/default_item_badges.xml",
+ "res/layout/detailed_item.xml"));
+ }
+
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/WrongImportDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/WrongImportDetectorTest.java
new file mode 100644
index 0000000..c44f204
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/WrongImportDetectorTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class WrongImportDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new WrongImportDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "src/test/pkg/BadImport.java:5: Warning: Don't include android.R here; use a fully qualified name for each usage instead [SuspiciousImport]\n" +
+ "import android.R;\n" +
+ "~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ // Java files must be renamed in source tree
+ "src/test/pkg/BadImport.java.txt=>src/test/pkg/BadImport.java"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/WrongLocationDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/WrongLocationDetectorTest.java
new file mode 100644
index 0000000..f30a604
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/WrongLocationDetectorTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class WrongLocationDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new WrongLocationDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/layout/alias.xml:17: Error: This file should be placed in a values/ folder, not a layout/ folder [WrongFolder]\n" +
+ "<resources>\n" +
+ "^\n" +
+ "1 errors, 0 warnings\n",
+
+ lintProject("res/values/strings.xml=>res/layout/alias.xml"));
+ }
+
+ public void testOk() throws Exception {
+ assertEquals("No warnings.",
+
+ lintProject("res/values/strings.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/AbstractActivity.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/AbstractActivity.java.txt
new file mode 100644
index 0000000..a9e0400
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/AbstractActivity.java.txt
@@ -0,0 +1,6 @@
+package test.pkg;
+
+import android.app.Activity;
+
+public abstract class AbstractActivity extends Activity {
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/AndroidManifest.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/AndroidManifest.xml
new file mode 100644
index 0000000..75ef31c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/allowbackup.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/allowbackup.xml
new file mode 100644
index 0000000..2a95252
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/allowbackup.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:allowBackup="true" >
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/allowbackup_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/allowbackup_ignore.xml
new file mode 100644
index 0000000..72f8bb4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/allowbackup_ignore.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ tools:ignore="AllowBackup"
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest.class.data
new file mode 100644
index 0000000..4e2b100
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest.java.txt
new file mode 100644
index 0000000..456dd8b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest.java.txt
@@ -0,0 +1,52 @@
+package test.pkg;
+
+import org.w3c.dom.DOMError;
+import org.w3c.dom.DOMErrorHandler;
+import org.w3c.dom.DOMLocator;
+
+import android.view.ViewGroup.LayoutParams;
+import android.app.Activity;
+import android.app.ApplicationErrorReport;
+import android.app.ApplicationErrorReport.BatteryInfo;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuff.Mode;
+import android.widget.Chronometer;
+import android.widget.GridLayout;
+import dalvik.bytecode.OpcodeInfo;
+
+public class ApiCallTest extends Activity {
+ public void method(Chronometer chronometer, DOMLocator locator) {
+ // Virtual call
+ getActionBar(); // API 11
+
+ // Class references (no call or field access)
+ DOMError error = null; // API 8
+ Class<?> clz = DOMErrorHandler.class; // API 8
+
+ // Method call
+ chronometer.getOnChronometerTickListener(); // API 3
+
+ // Inherited method call (from TextView
+ chronometer.setTextIsSelectable(true); // API 11
+
+ // Field access
+ int field = OpcodeInfo.MAXIMUM_VALUE; // API 11
+ int fillParent = LayoutParams.FILL_PARENT; // API 1
+ // This is a final int, which means it gets inlined
+ int matchParent = LayoutParams.MATCH_PARENT; // API 8
+ // Field access: non final
+ BatteryInfo batteryInfo = getReport().batteryInfo;
+
+ // Enum access
+ Mode mode = PorterDuff.Mode.OVERLAY; // API 11
+ }
+
+ // Return type
+ GridLayout getGridLayout() { // API 14
+ return null;
+ }
+
+ private ApplicationErrorReport getReport() {
+ return null;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.class.data
new file mode 100644
index 0000000..23ef1bd
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.java.txt
new file mode 100644
index 0000000..ae02a81
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.java.txt
@@ -0,0 +1,45 @@
+package test.pkg;
+
+import android.os.Build;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+
+public class ApiCallTest10 extends View {
+ public ApiCallTest10() {
+ super(null, null, 0);
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ onPopulateAccessibilityEvent(event); // Shouldn't warn here: method
+ // exists locally
+ return true;
+ }
+ return super.dispatchPopulateAccessibilityEvent(event);
+ }
+
+ @Override
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event); // Valid lint warning
+ // Additional override code here:
+ }
+
+ @Override
+ protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
+ return super.dispatchGenericFocusedEvent(event); // Should flag this
+ }
+
+ protected boolean dispatchHoverEvent(int event) {
+ return false;
+ }
+
+ public void test1() {
+ // Should flag this, because the local method has the wrong signature
+ dispatchHoverEvent(null);
+
+ // Shouldn't flag this, local method makes it available
+ dispatchGenericFocusedEvent(null);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11$MyActivity.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11$MyActivity.class.data
new file mode 100644
index 0000000..5368daf
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11$MyActivity.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11$MyLinear.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11$MyLinear.class.data
new file mode 100644
index 0000000..5ee9e96
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11$MyLinear.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11.class.data
new file mode 100644
index 0000000..17e10d6
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11.java.txt
new file mode 100644
index 0000000..8fb592c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11.java.txt
@@ -0,0 +1,50 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.app.ActionBar;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.widget.LinearLayout;
+
+public class ApiCallTest11 extends Activity {
+ MyActivity mActionBarHost;
+
+ public ActionBar getActionBar() {
+ return mActionBarHost.getActionBar();
+ }
+
+ public boolean isDestroyed() {
+ return true;
+ }
+
+ @SuppressLint("Override")
+ public void finishAffinity() {
+ }
+
+ private class MyLinear extends LinearLayout {
+ private Drawable mDividerDrawable;
+
+ public MyLinear(Context context) {
+ super(context);
+ }
+
+ /**
+ * Javadoc here
+ *
+ *
+ *
+ *
+ */
+ public void setDividerDrawable(Drawable dividerDrawable) {
+ mDividerDrawable = dividerDrawable;
+ }
+ }
+
+ private class MyActivity {
+ public ActionBar getActionBar() {
+ return null;
+ }
+ }
+}
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest12.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest12.class.data
new file mode 100644
index 0000000..4056133
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest12.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest12.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest12.java.txt
new file mode 100644
index 0000000..6ac71db
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest12.java.txt
@@ -0,0 +1,30 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.os.Build;
+
+import java.text.DateFormatSymbols;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+@SuppressWarnings({ "unused", "javadoc" })
+@SuppressLint("SimpleDateFormat")
+public class ApiCallTest12 {
+ public void test() {
+ // Normal SimpleDateFormat calls
+ new SimpleDateFormat();
+ new SimpleDateFormat("yyyy-MM-dd");
+ new SimpleDateFormat("yyyy-MM-dd", DateFormatSymbols.getInstance());
+ new SimpleDateFormat("yyyy-MM-dd", Locale.US);
+ new SimpleDateFormat("MMMM", Locale.US);
+
+ // Flag format strings requiring API 9
+ new SimpleDateFormat("yyyy-MM-dd LL", Locale.US);
+
+ SimpleDateFormat format = new SimpleDateFormat("cc yyyy-MM-dd");
+
+ // Escaped text
+ new SimpleDateFormat("MM-dd 'My Location'", Locale.US);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest2.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest2.class.data
new file mode 100644
index 0000000..32c3657
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest2.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest2.java.txt
new file mode 100644
index 0000000..aa6f344
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest2.java.txt
@@ -0,0 +1,9 @@
+package android.support.foo;
+
+import org.w3c.dom.DOMError;
+
+public class Foo {
+ private void foo() {
+ DOMError error = null; // API 8
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest3.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest3.class.data
new file mode 100644
index 0000000..3d39e74
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest3.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest3.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest3.java.txt
new file mode 100644
index 0000000..d1ea3e4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest3.java.txt
@@ -0,0 +1,12 @@
+package test.pkg;
+
+/**
+ * Call test where the parent class is some other project class which in turn
+ * extends the public API
+ */
+public class ApiCallTest3 extends Intermediate {
+ public void foo() {
+ // Virtual call
+ getActionBar(); // API 11
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$1.class.data
new file mode 100644
index 0000000..8d3fbf7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$InnerClass1$InnerInnerClass1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$InnerClass1$InnerInnerClass1.class.data
new file mode 100644
index 0000000..940b83d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$InnerClass1$InnerInnerClass1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$InnerClass1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$InnerClass1.class.data
new file mode 100644
index 0000000..4da3d3b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$InnerClass1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$InnerClass2.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$InnerClass2.class.data
new file mode 100644
index 0000000..c8e914b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4$InnerClass2.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4.class.data
new file mode 100644
index 0000000..b51d04a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4.java.txt
new file mode 100644
index 0000000..de6be04
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4.java.txt
@@ -0,0 +1,41 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.widget.GridLayout;
+
+@SuppressWarnings("unused")
+public class ApiCallTest4 {
+ public void foo() {
+ new GridLayout(null, null, 0);
+ }
+
+ @SuppressLint("NewApi")
+ void foo2() {
+ // Inner class suppressed via a method in outer class
+ new Runnable() {
+ @Override
+ public void run() {
+ new GridLayout(null, null, 0);
+ }
+ };
+ }
+
+ @SuppressLint("NewApi")
+ private class InnerClass1 {
+ void foo() {
+ new GridLayout(null, null, 0);
+ }
+
+ private class InnerInnerClass1 {
+ public void foo() {
+ new GridLayout(null, null, 0);
+ }
+ }
+ }
+
+ private class InnerClass2 {
+ public void foo() {
+ new GridLayout(null, null, 0);
+ }
+ }
+} \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest5.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest5.class.data
new file mode 100644
index 0000000..ad0cd48
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest5.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest5.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest5.java.txt
new file mode 100644
index 0000000..4be8258
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest5.java.txt
@@ -0,0 +1,23 @@
+package test.pkg;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.view.View;
+
+public class ApiCallTest5 extends View {
+ public ApiCallTest5(Context context) {
+ super(context);
+ }
+
+ @SuppressWarnings("unused")
+ @Override
+ @TargetApi(2)
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int measuredWidth = View.resolveSizeAndState(widthMeasureSpec,
+ widthMeasureSpec, 0);
+ int measuredHeight = resolveSizeAndState(heightMeasureSpec,
+ heightMeasureSpec, 0);
+ View.combineMeasuredStates(0, 0);
+ ApiCallTest5.combineMeasuredStates(0, 0);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest6.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest6.class.data
new file mode 100644
index 0000000..7c0f3a7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest6.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest6.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest6.java.txt
new file mode 100644
index 0000000..ae6e5fa
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest6.java.txt
@@ -0,0 +1,10 @@
+package test.pkg;
+
+import java.io.IOException;
+
+public class ApiCallTest6 {
+ public void test(Throwable throwable) {
+ // IOException(Throwable) requires API 9
+ IOException ioException = new IOException(throwable);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest7.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest7.class.data
new file mode 100644
index 0000000..e9f739d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest7.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest7.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest7.java.txt
new file mode 100644
index 0000000..37ad6a7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest7.java.txt
@@ -0,0 +1,14 @@
+package test.pkg;
+
+import java.io.IOException;
+
+@SuppressWarnings("serial")
+public class ApiCallTest7 extends IOException {
+ public ApiCallTest7(String message, Throwable cause) {
+ super(message, cause); // API 9
+ }
+
+ public void fun() throws IOException {
+ super.toString(); throw new IOException((Throwable) null); // API 9
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest8.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest8.class.data
new file mode 100644
index 0000000..b92e7d9
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest8.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest8.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest8.java.txt
new file mode 100644
index 0000000..f742ad1
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest8.java.txt
@@ -0,0 +1,10 @@
+package test.pkg;
+
+import android.text.style.LeadingMarginSpan;
+
+@SuppressWarnings("unused")
+public class ApiCallTest8 {
+ public void test() {
+ LeadingMarginSpan.LeadingMarginSpan2 span = null;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.class.data
new file mode 100644
index 0000000..f50ebab
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.java.txt
new file mode 100644
index 0000000..199231e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.java.txt
@@ -0,0 +1,19 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.widget.GridLayout;
+
+/** Test suppress on fields */
+public class ApiCallTest9 {
+ // Actual initialization code lives in the synthetic method <init>
+ private GridLayout field1 = new GridLayout(null);
+
+ // Actual initialization code lives in the synthetic method <clinit>
+ private static GridLayout field2 = new GridLayout(null);
+
+ @SuppressLint("NewApi")
+ private GridLayout field3 = new GridLayout(null);
+
+ @SuppressLint("NewApi")
+ private static GridLayout field4 = new GridLayout(null);
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest$LocalClass.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest$LocalClass.class.data
new file mode 100644
index 0000000..136eed5
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest$LocalClass.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest.class.data
new file mode 100644
index 0000000..7dc3d60
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest.java.txt
new file mode 100644
index 0000000..8626858
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest.java.txt
@@ -0,0 +1,42 @@
+package test.pkg;
+
+import org.w3c.dom.DOMErrorHandler;
+
+import android.annotation.TargetApi;
+
+// Test using the @TargetApi annotation to temporarily override
+// the required API levels
+@SuppressWarnings("unused")
+public class ApiTargetTest {
+ public void test1() {
+ // No annotation: should generate warning if manifest SDK < 8
+ Class<?> clz = DOMErrorHandler.class; // API 8
+ }
+
+ // Temporarily setting method min sdk to 12
+ @TargetApi(12)
+ public void test2() {
+ Class<?> clz = DOMErrorHandler.class; // API 8
+ }
+
+ // Temporarily setting method min sdk to 14
+ @TargetApi(4)
+ public void test3() {
+ Class<?> clz = DOMErrorHandler.class; // API 8
+ }
+
+ // Temporarily setting class min sdk to 12
+ @TargetApi(value=11)
+ public static class LocalClass {
+ public void test4() {
+ Class<?> clz = DOMErrorHandler.class; // API 8
+ }
+
+ // Overriding class min sdk: this should generate
+ // an API warning again
+ @TargetApi(7)
+ public void test5() {
+ Class<?> clz = DOMErrorHandler.class; // API 8
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2$1$1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2$1$1.class.data
new file mode 100644
index 0000000..f18f226
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2$1$1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2$1$2.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2$1$2.class.data
new file mode 100644
index 0000000..ac3863e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2$1$2.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2$1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2$1.class.data
new file mode 100644
index 0000000..f51c54b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2$1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2.class.data
new file mode 100644
index 0000000..defae98
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2.java.txt
new file mode 100644
index 0000000..7574805
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2.java.txt
@@ -0,0 +1,39 @@
+package test.pkg;
+
+import android.annotation.TargetApi;
+import android.widget.GridLayout;
+
+// Test using the @TargetApi annotation on inner classes and anonymous inner classes
+@SuppressWarnings("unused")
+public class ApiTargetTest2 {
+ @TargetApi(value=14)
+ void foo2() {
+ new Runnable() {
+ @Override
+ public void run() {
+ new GridLayout(null, null, 0);
+ }
+
+ void foo3() {
+ new Runnable() {
+ @Override
+ public void run() {
+ new GridLayout(null, null, 0);
+ }
+ };
+ }
+
+ @TargetApi(value=3)
+ void foo4() {
+ new Runnable() {
+ @Override
+ public void run() {
+ // This should be marked as an error since the effective target API is 3 here
+ new GridLayout(null, null, 0);
+ }
+ };
+ }
+
+ };
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/CloseTest.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/CloseTest.class.data
new file mode 100644
index 0000000..acb19e5
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/CloseTest.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/CloseTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/CloseTest.java.txt
new file mode 100644
index 0000000..dc3e538
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/CloseTest.java.txt
@@ -0,0 +1,9 @@
+package test.pkg;
+
+import android.database.sqlite.SQLiteStatement;
+
+public class CloseTest {
+ public void close(SQLiteStatement statement) {
+ statement.close();
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate$IntermediateCustomV.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate$IntermediateCustomV.class.data
new file mode 100644
index 0000000..cbf323c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate$IntermediateCustomV.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate.class.data
new file mode 100644
index 0000000..8d187da
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate.java.txt
new file mode 100644
index 0000000..fea5c4f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate.java.txt
@@ -0,0 +1,15 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.widget.Button;
+
+/** Local activity */
+public abstract class Intermediate extends Activity {
+
+ /** Local Custom view */
+ public abstract static class IntermediateCustomV extends Button {
+ public IntermediateCustomV() {
+ super(null);
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest1.class.data
new file mode 100644
index 0000000..60d4e81
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest1.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest1.java.txt
new file mode 100644
index 0000000..a8775d7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest1.java.txt
@@ -0,0 +1,137 @@
+package test.pkg;
+
+import org.w3c.dom.DOMError;
+import org.w3c.dom.DOMErrorHandler;
+import org.w3c.dom.DOMLocator;
+
+import android.view.ViewGroup.LayoutParams;
+import android.annotations.tools.SuppressLint;
+import android.app.Activity;
+import android.app.ApplicationErrorReport;
+import android.app.ApplicationErrorReport.BatteryInfo;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuff.Mode;
+import android.widget.Chronometer;
+import android.widget.GridLayout;
+import dalvik.bytecode.OpcodeInfo;
+
+public class SuppressTest1 extends Activity {
+ @SuppressLint("all")
+ public void method1(Chronometer chronometer, DOMLocator locator) {
+ // Virtual call
+ getActionBar(); // API 11
+
+ // Class references (no call or field access)
+ DOMError error = null; // API 8
+ Class<?> clz = DOMErrorHandler.class; // API 8
+
+ // Method call
+ chronometer.getOnChronometerTickListener(); // API 3
+
+ // Inherited method call (from TextView
+ chronometer.setTextIsSelectable(true); // API 11
+
+ // Field access
+ int field = OpcodeInfo.MAXIMUM_VALUE; // API 11
+ int fillParent = LayoutParams.FILL_PARENT; // API 1
+ // This is a final int, which means it gets inlined
+ int matchParent = LayoutParams.MATCH_PARENT; // API 8
+ // Field access: non final
+ BatteryInfo batteryInfo = getReport().batteryInfo;
+
+ // Enum access
+ Mode mode = PorterDuff.Mode.OVERLAY; // API 11
+ }
+
+ @SuppressLint("NewApi")
+ public void method2(Chronometer chronometer, DOMLocator locator) {
+ // Virtual call
+ getActionBar(); // API 11
+
+ // Class references (no call or field access)
+ DOMError error = null; // API 8
+ Class<?> clz = DOMErrorHandler.class; // API 8
+
+ // Method call
+ chronometer.getOnChronometerTickListener(); // API 3
+
+ // Inherited method call (from TextView
+ chronometer.setTextIsSelectable(true); // API 11
+
+ // Field access
+ int field = OpcodeInfo.MAXIMUM_VALUE; // API 11
+ int fillParent = LayoutParams.FILL_PARENT; // API 1
+ // This is a final int, which means it gets inlined
+ int matchParent = LayoutParams.MATCH_PARENT; // API 8
+ // Field access: non final
+ BatteryInfo batteryInfo = getReport().batteryInfo;
+
+ // Enum access
+ Mode mode = PorterDuff.Mode.OVERLAY; // API 11
+ }
+
+ @SuppressLint("SomethingElse")
+ public void method3(Chronometer chronometer, DOMLocator locator) {
+ // Virtual call
+ getActionBar(); // API 11
+
+ // Class references (no call or field access)
+ DOMError error = null; // API 8
+ Class<?> clz = DOMErrorHandler.class; // API 8
+
+ // Method call
+ chronometer.getOnChronometerTickListener(); // API 3
+
+ // Inherited method call (from TextView
+ chronometer.setTextIsSelectable(true); // API 11
+
+ // Field access
+ int field = OpcodeInfo.MAXIMUM_VALUE; // API 11
+ int fillParent = LayoutParams.FILL_PARENT; // API 1
+ // This is a final int, which means it gets inlined
+ int matchParent = LayoutParams.MATCH_PARENT; // API 8
+ // Field access: non final
+ BatteryInfo batteryInfo = getReport().batteryInfo;
+
+ // Enum access
+ Mode mode = PorterDuff.Mode.OVERLAY; // API 11
+ }
+
+ @SuppressLint({"SomethingElse", "NewApi"})
+ public void method4(Chronometer chronometer, DOMLocator locator) {
+ // Virtual call
+ getActionBar(); // API 11
+
+ // Class references (no call or field access)
+ DOMError error = null; // API 8
+ Class<?> clz = DOMErrorHandler.class; // API 8
+
+ // Method call
+ chronometer.getOnChronometerTickListener(); // API 3
+
+ // Inherited method call (from TextView
+ chronometer.setTextIsSelectable(true); // API 11
+
+ // Field access
+ int field = OpcodeInfo.MAXIMUM_VALUE; // API 11
+ int fillParent = LayoutParams.FILL_PARENT; // API 1
+ // This is a final int, which means it gets inlined
+ int matchParent = LayoutParams.MATCH_PARENT; // API 8
+ // Field access: non final
+ BatteryInfo batteryInfo = getReport().batteryInfo;
+
+ // Enum access
+ Mode mode = PorterDuff.Mode.OVERLAY; // API 11
+ }
+
+ // Return type
+ @SuppressLint("NewApi")
+ GridLayout getGridLayout() { // API 14
+ return null;
+ }
+
+ @SuppressLint("all")
+ private ApplicationErrorReport getReport() {
+ return null;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest2.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest2.class.data
new file mode 100644
index 0000000..fdb512b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest2.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest2.java.txt
new file mode 100644
index 0000000..e325413
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest2.java.txt
@@ -0,0 +1,25 @@
+package test.pkg;
+
+import org.w3c.dom.DOMLocator;
+
+import android.annotations.tools.SuppressLint;
+import android.app.Activity;
+import android.app.ApplicationErrorReport;
+import android.widget.Chronometer;
+import android.widget.GridLayout;
+
+@SuppressLint("all")
+public class SuppressTest2 extends Activity {
+ public void method(Chronometer chronometer, DOMLocator locator) {
+ getActionBar(); // API 11
+ }
+
+ // Return type
+ GridLayout getGridLayout() { // API 14
+ return null;
+ }
+
+ private ApplicationErrorReport getReport() {
+ return null;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest3.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest3.class.data
new file mode 100644
index 0000000..23e8b5c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest3.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest3.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest3.java.txt
new file mode 100644
index 0000000..c430ce4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest3.java.txt
@@ -0,0 +1,25 @@
+package test.pkg;
+
+import org.w3c.dom.DOMLocator;
+
+import android.annotations.tools.SuppressLint;
+import android.app.Activity;
+import android.app.ApplicationErrorReport;
+import android.widget.Chronometer;
+import android.widget.GridLayout;
+
+@SuppressLint("NewApi")
+public class SuppressTest3 extends Activity {
+ public void method(Chronometer chronometer, DOMLocator locator) {
+ getActionBar(); // API 11
+ }
+
+ // Return type
+ GridLayout getGridLayout() { // API 14
+ return null;
+ }
+
+ private ApplicationErrorReport getReport() {
+ return null;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest4.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest4.class.data
new file mode 100644
index 0000000..c85a4ff
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest4.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest4.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest4.java.txt
new file mode 100644
index 0000000..2fa2af8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest4.java.txt
@@ -0,0 +1,21 @@
+package test.pkg;
+
+import android.annotations.tools.SuppressLint;
+import android.app.Activity;
+import android.app.ApplicationErrorReport;
+import android.app.ApplicationErrorReport.BatteryInfo;
+
+public class SuppressTest4 extends Activity {
+ public void method() {
+
+ // These annotations within the method do not end up
+ // in the bytecode, so they have no effect. We need a
+ // lint annotation check to find these.
+
+ @SuppressLint("NewApi")
+ ApplicationErrorReport report = null;
+
+ @SuppressLint("NewApi")
+ BatteryInfo batteryInfo = report.batteryInfo;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestEnum.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestEnum.class.data
new file mode 100644
index 0000000..fa676b9
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestEnum.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestEnum.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestEnum.java.txt
new file mode 100644
index 0000000..2d68b28
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestEnum.java.txt
@@ -0,0 +1,67 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.PorterDuff;
+
+@SuppressWarnings("incomplete-switch")
+public class TestEnum {
+ public static void test1(final CompressFormat format) {
+ switch (format) {
+ case JPEG: {
+ System.out.println("jpeg");
+ break;
+ }
+ default: {
+ System.out.println("Default");
+ }
+ }
+ }
+
+ public static void test2(final PorterDuff.Mode mode) {
+ switch (mode) {
+ case CLEAR: {
+ System.out.println("clear");
+ }
+ case OVERLAY: {
+ System.out.println("add");
+ break;
+ }
+ }
+
+ // Second usage: should also complain here
+ switch (mode) {
+ case CLEAR: {
+ System.out.println("clear");
+ }
+ case OVERLAY: {
+ System.out.println("add");
+ break;
+ }
+ }
+ }
+
+ @SuppressLint("NewApi")
+ public static void test3(PorterDuff.Mode mode) {
+ // Third usage: no complaint because it's suppressed
+ switch (mode) {
+ case CLEAR: {
+ System.out.println("clear");
+ }
+ case OVERLAY: {
+ System.out.println("add");
+ break;
+ }
+ }
+ }
+
+ public static void test4(final android.renderscript.Element.DataType type) {
+ // Switch usage where the whole underlying enum requires a higher API level:
+ // test customized error message
+ switch (type) {
+ case RS_FONT: {
+ System.out.println("font");
+ }
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestLint.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestLint.class.data
new file mode 100644
index 0000000..9e74a7a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestLint.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/classpath b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/classpath
new file mode 100644
index 0000000..a4763d1
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/colors.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/colors.xml
new file mode 100644
index 0000000..fc84a61
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/colors.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="color1">@android:color/black</color>
+ <!-- Requires API 14 -->
+ <color name="color2">@android:color/holo_blue_bright</color>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/holomanifest.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/holomanifest.xml
new file mode 100644
index 0000000..8890afc
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/holomanifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="4" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.Holo" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/layout.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/layout.xml
new file mode 100644
index 0000000..83b6b0a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/layout.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <!-- Requires API 5 -->
+
+ <QuickContactBadge
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <!-- Requires API 11 -->
+
+ <CalendarView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
+
+ <!-- Requires API 14 -->
+
+ <GridLayout
+ foo="@android:attr/actionBarSplitStyle"
+ bar="@android:color/holo_red_light"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" >
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
+ </GridLayout>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/layout_targetapi.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/layout_targetapi.xml
new file mode 100644
index 0000000..51ce945
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/layout_targetapi.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="fill_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ tools:targetApi="11" >
+
+ <!-- Requires API 5 -->
+
+ <QuickContactBadge
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <!-- Requires API 11 -->
+
+ <CalendarView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
+
+ <!-- Requires API 14 -->
+
+ <GridLayout
+ foo="@android:attr/actionBarSplitStyle"
+ bar="@android:color/holo_red_light"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ tools:targetApi="ICE_CREAM_SANDWICH" >
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
+ </GridLayout>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk1.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk1.xml
new file mode 100644
index 0000000..6a9c919
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk1.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="1" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk10.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk10.xml
new file mode 100644
index 0000000..2896fc8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk10.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="10" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk14.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk14.xml
new file mode 100644
index 0000000..391a8aa
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk14.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk17.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk17.xml
new file mode 100644
index 0000000..1837db9
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk17.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="17" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk2.xml
new file mode 100644
index 0000000..23a15be
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk2.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="2" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk4.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk4.xml
new file mode 100644
index 0000000..be95440
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/minsdk4.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="4" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/themes.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/themes.xml
new file mode 100644
index 0000000..478940e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/themes.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="Theme" parent="android:Theme"/>
+
+ <style name="Theme.Test" parent="android:style/Theme.Light">
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <!-- Requires API 14 -->
+ <item name="android:windowBackground"> @android:color/holo_red_light </item>
+ </style>
+
+ <style name="Theme.Test.Transparent">
+ <item name="android:windowBackground">@android:color/transparent</item>
+ </style>
+
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/unsupported.jar.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/unsupported.jar.data
new file mode 100644
index 0000000..7cbedc1
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/unsupported.jar.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/view.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/view.xml
new file mode 100644
index 0000000..2f9fc84
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/view.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <!-- Requires API 5 -->
+
+ <view
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ class="QuickContactBadge" />
+
+ <!-- Requires API 11 -->
+
+ <view
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ class="CalendarView" />
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ unknown="?android:attr/dividerHorizontal"
+ android:textColor="?android:attr/textColorLinkInverse" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/broken-manifest.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/broken-manifest.xml
new file mode 100644
index 0000000..e55e908
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/broken-manifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.helloworld"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application android:icon="@drawable/icon" android:label="@string/app_name">
+ <activity android:name=".HelloWorld"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ </application>
+ <uses-sdk android:minSdkVersion="Froyo" />
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/broken-manifest2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/broken-manifest2.xml
new file mode 100644
index 0000000..307046b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/broken-manifest2.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.helloworld"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application android:icon="@drawable/icon" android:label="@string/app_name">
+ <!-- Wrong declaration locations -->
+ <uses-sdk android:minSdkVersion="Froyo" />
+ <uses-permission />
+ <permission />
+ <permission-tree />
+ <permission-group />
+ <instrumentation />
+ <uses-sdk />
+ <uses-configuration />
+ <uses-feature />
+ <supports-screens />
+ <compatible-screens />
+ <supports-gl-texture />
+
+ </application>
+
+ <!-- Wrong declaration locations -->
+ <uses-library />
+ <activity android:name=".HelloWorld"
+ android:label="@string/app_name" />
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/.classpath b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/.classpath
new file mode 100644
index 0000000..a4763d1
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AbstractActivity.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AbstractActivity.class.data
new file mode 100644
index 0000000..85ebb78
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AbstractActivity.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AbstractActivity.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AbstractActivity.java.txt
new file mode 100644
index 0000000..a9e0400
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AbstractActivity.java.txt
@@ -0,0 +1,6 @@
+package test.pkg;
+
+import android.app.Activity;
+
+public abstract class AbstractActivity extends Activity {
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AndroidManifest.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AndroidManifest.xml
new file mode 100644
index 0000000..2896fc8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="10" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AndroidManifestReg.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AndroidManifestReg.xml
new file mode 100644
index 0000000..82fda69
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AndroidManifestReg.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.pkg.Foo"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="15" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name="CommentsActivity"
+ android:label="@string/app_name" >
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AndroidManifestWrongRegs.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AndroidManifestWrongRegs.xml
new file mode 100644
index 0000000..efe7213
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AndroidManifestWrongRegs.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.pkg"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="10" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <!-- These registrations are bogus (wrong type) -->
+ <activity android:name=".TestProvider" />
+ <service android:name="test.pkg.TestProvider2" />
+ <provider android:name=".TestService" />
+ <receiver android:name="OnClickActivity" />
+ <service android:name="TestReceiver" />
+
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class1$Class4.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class1$Class4.class.data
new file mode 100644
index 0000000..bfd88db
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class1$Class4.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class1.class.data
new file mode 100644
index 0000000..cee3058
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class2$Class3.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class2$Class3.class.data
new file mode 100644
index 0000000..2a58332
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class2$Class3.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class2.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class2.class.data
new file mode 100644
index 0000000..1b72f03
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class2.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CommentsActivity.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CommentsActivity.class.data
new file mode 100644
index 0000000..7f9f23b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CommentsActivity.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CommentsActivity.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CommentsActivity.java.txt
new file mode 100644
index 0000000..941a01d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CommentsActivity.java.txt
@@ -0,0 +1,6 @@
+package test.pkg.Foo;
+
+import android.app.Activity;
+
+public class CommentsActivity extends Activity {
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView1.class.data
new file mode 100644
index 0000000..d6a8ad7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView1.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView1.java.txt
new file mode 100644
index 0000000..e871e74
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView1.java.txt
@@ -0,0 +1,9 @@
+package test.pkg;
+
+import android.view.View;
+
+public class CustomView1 extends View {
+ public CustomView1() {
+ super(null);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView2.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView2.class.data
new file mode 100644
index 0000000..0788ef3
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView2.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView2.java.txt
new file mode 100644
index 0000000..dccc8ec
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView2.java.txt
@@ -0,0 +1,12 @@
+package test.pkg;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.Button;
+
+public class CustomView2 extends Button {
+ public CustomView2(boolean foo,
+ Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView3.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView3.class.data
new file mode 100644
index 0000000..a4b7c7d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView3.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView3.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView3.java.txt
new file mode 100644
index 0000000..86d983f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView3.java.txt
@@ -0,0 +1,20 @@
+package test.pkg;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+public class CustomView3 extends TextView {
+
+ public CustomView3(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public CustomView3(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public CustomView3(Context context) {
+ super(context);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomViewTest.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomViewTest.class.data
new file mode 100644
index 0000000..e145fbc
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomViewTest.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment1.class.data
new file mode 100644
index 0000000..11a98dd
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment2.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment2.class.data
new file mode 100644
index 0000000..d77579a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment2.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment3.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment3.class.data
new file mode 100644
index 0000000..b1ec17d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment3.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment4.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment4.class.data
new file mode 100644
index 0000000..f89f8ed
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment4.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment5.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment5.class.data
new file mode 100644
index 0000000..4a23e03
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment5.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment6.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment6.class.data
new file mode 100644
index 0000000..2e10e12
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$Fragment6.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$NotAFragment.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$NotAFragment.class.data
new file mode 100644
index 0000000..8f5b827
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$NotAFragment.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$ValidFragment1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$ValidFragment1.class.data
new file mode 100644
index 0000000..a3354a7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest$ValidFragment1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest.class.data
new file mode 100644
index 0000000..6cc8387
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest.java.txt
new file mode 100644
index 0000000..d27c04a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest.java.txt
@@ -0,0 +1,55 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.app.Fragment;
+
+@SuppressWarnings("unused")
+public class FragmentTest {
+
+ // Should be public
+ private static class Fragment1 extends Fragment {
+
+ }
+
+ // Should be static
+ public class Fragment2 extends Fragment {
+
+ }
+
+ // Should have a public constructor
+ public static class Fragment3 extends Fragment {
+ private Fragment3() {
+ }
+ }
+
+ // Should have a public constructor with no arguments
+ public static class Fragment4 extends Fragment {
+ private Fragment4(int dummy) {
+ }
+ }
+
+ // Should *only* have the default constructor, not the
+ // multi-argument one
+ public static class Fragment5 extends Fragment {
+ public Fragment5() {
+ }
+ public Fragment5(int dummy) {
+ }
+ }
+
+ // Suppressed
+ @SuppressLint("ValidFragment")
+ public static class Fragment6 extends Fragment {
+ private Fragment6() {
+ }
+ }
+
+ public static class ValidFragment1 extends Fragment {
+ public ValidFragment1() {
+ }
+ }
+
+ // (Not a fragment)
+ private class NotAFragment {
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.class.data
new file mode 100644
index 0000000..73a9947
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.jar.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.jar.data
new file mode 100644
index 0000000..f5ef6d1
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.jar.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.java.txt
new file mode 100644
index 0000000..25f3421
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.java.txt
@@ -0,0 +1,59 @@
+package test.bytecode;
+
+public class GetterTest {
+ private int mFoo1;
+ private String mFoo2;
+ private int mBar1;
+ private static int sFoo4;
+
+ public int getFoo1() {
+ return mFoo1;
+ }
+
+ public String getFoo2() {
+ return mFoo2;
+ }
+
+ public int isBar1() {
+ return mBar1;
+ }
+
+ // Not "plain" getters:
+
+ public String getFoo3() {
+ // NOT a plain getter
+ if (mFoo2 == null) {
+ mFoo2 = "";
+ }
+ return mFoo2;
+ }
+
+ public int getFoo4() {
+ // NOT a plain getter (using static)
+ return sFoo4;
+ }
+
+ public int getFoo5(int x) {
+ // NOT a plain getter (has extra argument)
+ return sFoo4;
+ }
+
+ public int isBar2(String s) {
+ // NOT a plain getter (has extra argument)
+ return mFoo1;
+ }
+
+ public void test() {
+ getFoo1();
+ getFoo2();
+ getFoo3();
+ getFoo4();
+ getFoo5(42);
+ isBar1();
+ isBar2("foo");
+ this.getFoo1();
+ this.getFoo2();
+ this.getFoo3();
+ this.getFoo4();
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest$1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest$1.class.data
new file mode 100644
index 0000000..ae65532
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest$1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest$Inner.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest$Inner.class.data
new file mode 100644
index 0000000..3975896
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest$Inner.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest$StaticInner.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest$StaticInner.class.data
new file mode 100644
index 0000000..690ee89
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest$StaticInner.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest.class.data
new file mode 100644
index 0000000..93f9999
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest.java.txt
new file mode 100644
index 0000000..7622c98
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest.java.txt
@@ -0,0 +1,24 @@
+package test.pkg;
+
+import android.os.Handler;
+import android.os.Message;
+
+public class HandlerTest extends Handler { // OK
+ public static class StaticInner extends Handler { // OK
+ public void dispatchMessage(Message msg) {
+ super.dispatchMessage(msg);
+ };
+ }
+ public class Inner extends Handler { // ERROR
+ public void dispatchMessage(Message msg) {
+ super.dispatchMessage(msg);
+ };
+ }
+ void method() {
+ Handler anonymous = new Handler() { // ERROR
+ public void dispatchMessage(Message msg) {
+ super.dispatchMessage(msg);
+ };
+ };
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/LocaleTest.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/LocaleTest.class.data
new file mode 100644
index 0000000..2b10aa9
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/LocaleTest.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/LocaleTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/LocaleTest.java.txt
new file mode 100644
index 0000000..3c60c9d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/LocaleTest.java.txt
@@ -0,0 +1,37 @@
+package test.pkg;
+
+import java.text.*;
+import java.util.*;
+
+public class LocaleTest {
+ public void testStrings() {
+ System.out.println("OK".toUpperCase(Locale.getDefault()));
+ System.out.println("OK".toUpperCase(Locale.US));
+ System.out.println("OK".toUpperCase(Locale.CHINA));
+ System.out.println("WRONG".toUpperCase());
+
+ System.out.println("OK".toLowerCase(Locale.getDefault()));
+ System.out.println("OK".toLowerCase(Locale.US));
+ System.out.println("OK".toLowerCase(Locale.CHINA));
+ System.out.println("WRONG".toLowerCase());
+
+ String.format(Locale.getDefault(), "OK: %f", 1.0f);
+ String.format("OK: %x %A %c %b %B %h %n %%", 1, 2, 'c', true, false, 5);
+ String.format("WRONG: %f", 1.0f); // Implies locale
+ String.format("WRONG: %1$f", 1.0f);
+ String.format("WRONG: %e", 1.0f);
+ String.format("WRONG: %d", 1.0f);
+ String.format("WRONG: %g", 1.0f);
+ String.format("WRONG: %g", 1.0f);
+ String.format("WRONG: %1$tm %1$te,%1$tY",
+ new GregorianCalendar(2012, GregorianCalendar.AUGUST, 27));
+ }
+
+ @android.annotation.SuppressLint("NewApi") // DateFormatSymbols requires API 9
+ public void testSimpleDateFormat() {
+ new SimpleDateFormat(); // WRONG
+ new SimpleDateFormat("yyyy-MM-dd"); // WRONG
+ new SimpleDateFormat("yyyy-MM-dd", DateFormatSymbols.getInstance()); // WRONG
+ new SimpleDateFormat("yyyy-MM-dd", Locale.US); // OK
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/MathTest.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/MathTest.class.data
new file mode 100644
index 0000000..6647f1c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/MathTest.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/MathTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/MathTest.java.txt
new file mode 100644
index 0000000..0193f81
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/MathTest.java.txt
@@ -0,0 +1,21 @@
+package test.bytecode;
+
+import android.util.FloatMath;
+
+//Test data for the MathDetector
+public class MathTest {
+ public float floatResult;
+ public double doubleResult;
+
+ public void floatToFloatTest(float x, double y, int z) {
+ floatResult = FloatMath.cos(x);
+ floatResult = FloatMath.sin((float) y);
+ floatResult = android.util.FloatMath.ceil((float) y);
+ System.out.println(FloatMath.floor(x));
+ System.out.println(FloatMath.sqrt(z));
+
+ // No warnings for plain math
+ floatResult = (float) Math.cos(x);
+ floatResult = (float) java.lang.Math.sin(x);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/OnClickActivity.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/OnClickActivity.class.data
new file mode 100644
index 0000000..216a865
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/OnClickActivity.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/OnClickActivity.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/OnClickActivity.java.txt
new file mode 100644
index 0000000..557ba0a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/OnClickActivity.java.txt
@@ -0,0 +1,48 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.util.Log;
+import android.view.View;
+
+/** Test data for the OnClickDetector */
+public class OnClickActivity extends Activity {
+ // Wrong argument type 1
+ public void wrong1() {
+ }
+
+ // Wrong argument type 2
+ public void wrong2(int i) {
+ }
+
+ // Wrong argument type 3
+ public void wrong3(View view, int i) {
+ }
+
+ // Wrong return type
+ public int wrong4(View view) {
+ return 0;
+ }
+
+ // Wrong modifier (not public)
+ void wrong5(View view) {
+ }
+
+ // Wrong modifier (is static)
+ public static void wrong6(View view) {
+ }
+
+ public void ok(View view) {
+ }
+
+ // Ok: Unicode escapes
+ public void my\u1234method(View view) {
+ }
+
+ // Typo
+ public void simple_tyop(View view) {
+ }
+
+ void wrong7(View view) {
+ Log.i("x", "wrong7: called");
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/SecureRandomTest.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/SecureRandomTest.class.data
new file mode 100644
index 0000000..3236187
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/SecureRandomTest.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/SecureRandomTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/SecureRandomTest.java.txt
new file mode 100644
index 0000000..c05fbd9
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/SecureRandomTest.java.txt
@@ -0,0 +1,42 @@
+package test.pkg;
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+public class SecureRandomTest {
+ private static final long FIXED_SEED = 1000L;
+ protected int getDynamicSeed() { return 1; }
+
+ public void testLiterals() {
+ SecureRandom random1 = new SecureRandom();
+ random1.setSeed(System.currentTimeMillis()); // OK
+ random1.setSeed(getDynamicSeed()); // OK
+ random1.setSeed(0); // Wrong
+ random1.setSeed(1); // Wrong
+ random1.setSeed((int)1023); // Wrong
+ random1.setSeed(1023L); // Wrong
+ random1.setSeed(FIXED_SEED); // Wrong
+ }
+
+ public void testRandomTypeOk() {
+ Random random2 = new Random();
+ random2.setSeed(0); // OK
+ }
+
+ public void testRandomTypeWrong() {
+ Random random3 = new SecureRandom();
+ random3.setSeed(0); // Wrong: owner is java/util/Random, but applied to SecureRandom object
+ }
+
+ public void testBytesOk() {
+ SecureRandom random1 = new SecureRandom();
+ byte[] seed = random1.generateSeed(4);
+ random1.setSeed(seed); // OK
+ }
+
+ public void testBytesWrong() {
+ SecureRandom random2 = new SecureRandom();
+ byte[] seed = new byte[3];
+ random2.setSeed(seed); // Wrong
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestFieldGetter.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestFieldGetter.class.data
new file mode 100644
index 0000000..d922751
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestFieldGetter.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestFieldGetter.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestFieldGetter.java.txt
new file mode 100644
index 0000000..00da161
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestFieldGetter.java.txt
@@ -0,0 +1,36 @@
+package test.pkg;
+
+import java.io.File;
+import java.util.List;
+
+import android.content.Context;
+
+public class TestFieldGetter {
+ private int path;
+ private int foo;
+
+ public int getPath() {
+ return path;
+ }
+
+ public int getFoo() {
+ return foo;
+ }
+
+ public void test(TestFieldGetter other) {
+ getPath(); // Should be flagged
+ other.getPath(); // Ignore
+ File file = new File("/dummy");
+ file.getPath(); // Ignore
+ }
+
+ public static void test2(TestFieldGetter other) {
+ other.getPath(); // Ignore
+ }
+
+ public class Inner extends TestFieldGetter {
+ public void test() {
+ getFoo(); // Ignore
+ }
+ }
+} \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider.class.data
new file mode 100644
index 0000000..945742f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider.java.txt
new file mode 100644
index 0000000..2bf1bb8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider.java.txt
@@ -0,0 +1,40 @@
+package test.pkg;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class TestProvider extends ContentProvider {
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public boolean onCreate() {
+ return false;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+ return null;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection,
+ String[] selectionArgs) {
+ return 0;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider2.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider2.class.data
new file mode 100644
index 0000000..0973dbe
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider2.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider2.java.txt
new file mode 100644
index 0000000..881975d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider2.java.txt
@@ -0,0 +1,4 @@
+package test.pkg;
+
+public class TestProvider2 extends TestProvider {
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver$1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver$1.class.data
new file mode 100644
index 0000000..7ede85a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver$1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver.class.data
new file mode 100644
index 0000000..6180e40
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver.java.txt
new file mode 100644
index 0000000..90893c8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver.java.txt
@@ -0,0 +1,21 @@
+package test.pkg;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class TestReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ }
+
+ // Anonymous classes should NOT be counted as a must-register
+ private BroadcastReceiver dummy() {
+ return new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ }
+ };
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestService.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestService.class.data
new file mode 100644
index 0000000..a98f7aa
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestService.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestService.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestService.java.txt
new file mode 100644
index 0000000..d3f128a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestService.java.txt
@@ -0,0 +1,14 @@
+package test.pkg;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class TestService extends Service {
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/ViewTagTest.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/ViewTagTest.class.data
new file mode 100644
index 0000000..f26032c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/ViewTagTest.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/ViewTagTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/ViewTagTest.java.txt
new file mode 100644
index 0000000..8e72fd0
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/ViewTagTest.java.txt
@@ -0,0 +1,37 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+@SuppressWarnings("unused")
+public abstract class ViewTagTest {
+ public View newView(Context context, ViewGroup group, Cursor cursor1,
+ MatrixCursor cursor2) {
+ LayoutInflater inflater = LayoutInflater.from(context);
+ View view = inflater.inflate(android.R.layout.activity_list_item, null);
+ view.setTag(android.R.id.background, "Some random tag"); // OK
+ view.setTag(android.R.id.button1, group); // ERROR
+ view.setTag(android.R.id.icon, view.findViewById(android.R.id.icon)); // ERROR
+ view.setTag(android.R.id.icon1, cursor1); // ERROR
+ view.setTag(android.R.id.icon2, cursor2); // ERROR
+ view.setTag(android.R.id.copy, new MyViewHolder()); // ERROR
+ return view;
+ }
+
+ @SuppressLint("ViewTag")
+ public void checkSuppress(Context context, View view) {
+ view.setTag(android.R.id.icon, view.findViewById(android.R.id.icon));
+ }
+
+ private class MyViewHolder {
+ View view;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity1.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity1.class.data
new file mode 100644
index 0000000..d4733e6
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity1.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity1.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity1.java.txt
new file mode 100644
index 0000000..0b14691
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity1.java.txt
@@ -0,0 +1,17 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.PowerManager;
+
+public class WakelockActivity1 extends Activity {
+ private PowerManager.WakeLock mWakeLock;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ PowerManager manager = (PowerManager) getSystemService(POWER_SERVICE);
+ mWakeLock = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Test");
+ mWakeLock.acquire(); // Never released
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity2.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity2.class.data
new file mode 100644
index 0000000..89e35c1
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity2.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity2.java.txt
new file mode 100644
index 0000000..fa91a43
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity2.java.txt
@@ -0,0 +1,24 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.PowerManager;
+
+public class WakelockActivity2 extends Activity {
+ private PowerManager.WakeLock mWakeLock;
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mWakeLock != null && mWakeLock.isHeld()) {
+ mWakeLock.release(); // Should be done in onPause instead
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onDestroy();
+ if (mWakeLock != null && mWakeLock.isHeld()) {
+ mWakeLock.release(); // OK
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity3.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity3.class.data
new file mode 100644
index 0000000..b430519
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity3.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity3.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity3.java.txt
new file mode 100644
index 0000000..8a842eb
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity3.java.txt
@@ -0,0 +1,19 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.PowerManager;
+
+public class WakelockActivity3 extends Activity {
+ void wrongFlow() {
+ PowerManager manager = (PowerManager) getSystemService(POWER_SERVICE);
+ PowerManager.WakeLock lock =
+ manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Test");
+ lock.acquire();
+ randomCall();
+ lock.release(); // Should be in finally block
+ }
+
+ static void randomCall() {
+ System.out.println("test");
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity4.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity4.class.data
new file mode 100644
index 0000000..8905203
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity4.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity4.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity4.java.txt
new file mode 100644
index 0000000..9d6331f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity4.java.txt
@@ -0,0 +1,27 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.PowerManager;
+
+public class WakelockActivity4 extends Activity {
+ void wrongFlow2() {
+ getLock().acquire();
+ randomCall();
+ getLock().release(); // Should be in finally block
+ }
+
+ private PowerManager.WakeLock mLock;
+
+ PowerManager.WakeLock getLock() {
+ if (mLock == null) {
+ PowerManager manager = (PowerManager) getSystemService(POWER_SERVICE);
+ mLock = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Test");
+ }
+
+ return mLock;
+ }
+
+ static void randomCall() {
+ System.out.println("test");
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity5.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity5.class.data
new file mode 100644
index 0000000..9eca365
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity5.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity5.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity5.java.txt
new file mode 100644
index 0000000..060f2b1
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity5.java.txt
@@ -0,0 +1,19 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.PowerManager;
+
+public class WakelockActivity5 extends Activity {
+ void wrongFlow() {
+ PowerManager manager = (PowerManager) getSystemService(POWER_SERVICE);
+ PowerManager.WakeLock lock =
+ manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Test");
+ lock.acquire();
+ randomCall();
+ lock.release(); // Should be in finally block
+ }
+
+ static void randomCall() {
+ System.out.println("test");
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity6.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity6.class.data
new file mode 100644
index 0000000..51fdf69
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity6.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity6.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity6.java.txt
new file mode 100644
index 0000000..a122fa3
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity6.java.txt
@@ -0,0 +1,71 @@
+package test.pkg;
+
+import com.example.test3.BuildConfig;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;;
+
+public class WakelockActivity6 extends Activity {
+ void wrongFlow1() {
+ PowerManager manager = (PowerManager) getSystemService(POWER_SERVICE);
+ PowerManager.WakeLock lock =
+ manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Test");
+ lock.acquire();
+ if (getTaskId() == 50) {
+ randomCall();
+ } else {
+ lock.release(); // Wrong
+ }
+ }
+
+ void wrongFlow2(PowerManager.WakeLock lock) {
+ lock.acquire();
+ if (getTaskId() == 50) {
+ randomCall();
+ } else {
+ lock.release(); // Wrong
+ }
+ }
+
+ void okFlow1(WakeLock lock) {
+ lock.acquire();
+ try {
+ randomCall();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ lock.release(); // OK
+ }
+ }
+
+ public void checkNullGuard(WakeLock lock) {
+ lock.acquire();
+ if (lock != null) {
+ lock.release(); // OK
+ }
+ }
+
+ @SuppressLint("Wakelock")
+ public void checkDisabled1(PowerManager.WakeLock lock) {
+ lock.acquire();
+ randomCall();
+ lock.release(); // Wrong, but disabled
+ }
+
+ void wrongFlow3(WakeLock lock) {
+ int id = getTaskId();
+ lock.acquire();
+ if (id < 50) {
+ System.out.println(1);
+ } else {
+ System.out.println(2);
+ }
+ lock.release(); // Wrong
+ }
+
+ static void randomCall() {
+ System.out.println("test");
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity7.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity7.class.data
new file mode 100644
index 0000000..289b0d3
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity7.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity7.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity7.java.txt
new file mode 100644
index 0000000..be48dac
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity7.java.txt
@@ -0,0 +1,17 @@
+package test.pkg;
+
+import android.os.PowerManager.WakeLock;
+
+public class WakelockActivity7 {
+ public void test(WakeLock lock) {
+ try {
+ lock.acquire();
+ new Runnable() {
+ public void run() {
+ }
+ };
+ } finally {
+ lock.release();
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity8.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity8.class.data
new file mode 100644
index 0000000..5bd3ae2
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity8.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity8.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity8.java.txt
new file mode 100644
index 0000000..a6307c5
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity8.java.txt
@@ -0,0 +1,24 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+
+import com.google.io.demo.R;
+
+public class WakelockActivity8 extends Activity {
+ private WakeLock mWakeLock;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ PowerManager manager = (PowerManager) getSystemService(POWER_SERVICE);
+ mWakeLock = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Test");
+ mWakeLock.acquire();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classes.jar b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classes.jar
new file mode 100644
index 0000000..fa52dcf
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classes.jar
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classpath-jar b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classpath-jar
new file mode 100644
index 0000000..53f7d6c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classpath-jar
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes.jar"/>
+</classpath>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classpath-lib b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classpath-lib
new file mode 100644
index 0000000..e730df8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classpath-lib
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="lib" path="libs/library.jar"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/debuggable.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/debuggable.xml
new file mode 100644
index 0000000..1c234e4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/debuggable.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:debuggable="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate-manifest-ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate-manifest-ignore.xml
new file mode 100644
index 0000000..76cfd4d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate-manifest-ignore.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.example.helloworld"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <uses-sdk android:minSdkVersion="14" />
+ <application android:icon="@drawable/icon" android:label="@string/app_name" tools:ignore="DuplicateActivity">
+ <activity android:name=".HelloWorld"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="com.example.helloworld.HelloWorld"
+ android:label="@string/app_name">
+ </activity>
+
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate-manifest.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate-manifest.xml
new file mode 100644
index 0000000..e1fc3c6
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate-manifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.helloworld"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <uses-sdk android:minSdkVersion="14" />
+ <application android:icon="@drawable/icon" android:label="@string/app_name">
+ <activity android:name=".HelloWorld"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="com.example.helloworld.HelloWorld"
+ android:label="@string/app_name">
+ </activity>
+
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate_permissions1.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate_permissions1.xml
new file mode 100644
index 0000000..511fa46
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate_permissions1.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <permission android:name="foo.permission.SEND_SMS"
+ android:label="@string/foo"
+ android:description="@string/foo" />
+ <permission android:name="bar.permission.SEND_SMS"
+ android:label="@string/foo"
+ android:description="@string/foo" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate_permissions2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate_permissions2.xml
new file mode 100644
index 0000000..3729f79
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate_permissions2.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <permission android:name="foo.permission.SEND_SMS"
+ android:label="@string/foo"
+ android:description="@string/foo" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate_permissions3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate_permissions3.xml
new file mode 100644
index 0000000..a1a0638
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/duplicate_permissions3.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <permission android:name="bar.permission.SEND_SMS"
+ android:label="@string/foo"
+ android:description="@string/foo" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity0.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity0.xml
new file mode 100644
index 0000000..cc436d0
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity0.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass" >
+ </activity>
+ </application>
+
+</manifest>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity1.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity1.xml
new file mode 100644
index 0000000..0fc80f3
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity1.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </activity>
+ <activity
+ android:label="@string/app_name"
+ android:name="com.sample.service.mainClass" >
+ <intent-filter >
+ <action android:name="com.sample.service.mainClass" >
+ </action>
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity2.xml
new file mode 100644
index 0000000..2b4cf6a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity2.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass"
+ android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
+ android:process=":remote" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity3.xml
new file mode 100644
index 0000000..191c699
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity3.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
+ android:label="@string/app_name" >
+ <activity
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass"
+ android:process=":remote" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity4.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity4.xml
new file mode 100644
index 0000000..31345cc
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportactivity4.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass"
+ android:process=":remote" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportprovider1.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportprovider1.xml
new file mode 100644
index 0000000..02ec2e0
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportprovider1.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+
+ <!-- exported implicitly, fail -->
+ <provider
+ android:name="com.sample.provider.providerClass1"
+ android:authorities="com.sample.provider.providerData">
+ </provider>
+
+ <!-- exported explicitly, fail -->
+ <provider
+ android:exported="true"
+ android:name="com.sample.provider.providerClass2"
+ android:authorities="com.sample.provider.providerData">
+ </provider>
+
+ <!-- not exported, win -->
+ <provider
+ android:exported="false"
+ android:name="com.sample.provider.providerClass3"
+ android:authorities="com.sample.provider.providerData">
+ </provider>
+ </application>
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportprovider2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportprovider2.xml
new file mode 100644
index 0000000..4e3fc1b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportprovider2.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+
+ <!-- read+write permission attribute, win -->
+ <provider
+ android:name="com.sample.provider.providerClass"
+ android:authorities="com.sample.provider.providerData"
+ android:readPermission="com.sample.provider.READ_PERMISSON"
+ android:writePermission="com.sample.provider.WRITE_PERMISSON">
+ </provider>
+
+ <!-- permission attribute, win -->
+ <provider
+ android:name="com.sample.provider.providerClass"
+ android:authorities="com.sample.provider.providerData"
+ android:permission="com.sample.provider.PERMISSION">
+ </provider>
+
+ <!-- path-permission, win -->
+ <provider
+ android:name="com.sample.provider.providerClass"
+ android:authorities="com.sample.provider.providerData">
+ <path-permission
+ android:pathPrefix="/hello"
+ android:permission="com.sample.provider.PERMISSION">
+ </path-permission>
+ </provider>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver0.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver0.xml
new file mode 100644
index 0000000..f9c5190
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver0.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <receiver
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass" >
+ </receiver>
+ </application>
+
+</manifest>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver1.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver1.xml
new file mode 100644
index 0000000..0652d49
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver1.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <receiver
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </receiver>
+ </application>
+
+</manifest>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver2.xml
new file mode 100644
index 0000000..46d5dcb
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver2.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <receiver
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass"
+ android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
+ android:process=":remote" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </receiver>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver3.xml
new file mode 100644
index 0000000..bc3ec8a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver3.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
+ android:label="@string/app_name" >
+ <receiver
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass"
+ android:process=":remote" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </receiver>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver4.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver4.xml
new file mode 100644
index 0000000..5d9a826
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver4.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <receiver
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass"
+ android:process=":remote" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </receiver>
+ </application>
+
+</manifest>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver5.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver5.xml
new file mode 100644
index 0000000..afa74cf
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver5.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name">
+ <receiver>
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ </intent-filter>
+ </receiver>
+ </application>
+
+</manifest>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver6.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver6.xml
new file mode 100644
index 0000000..b1ce3e3
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportreceiver6.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+
+ <receiver android:name=".DockReceiver" >
+ <intent-filter>
+ <action android:name="android.intent.action.DOCK_EVENT" />
+ <action android:name="android.app.action.ENTER_CAR_MODE" />
+ </intent-filter>
+ </receiver>
+
+ <receiver
+ android:name="com.foo.BarReceiver"
+ android:enabled="false" >
+ <intent-filter>
+ <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
+ <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
+ </intent-filter>
+ </receiver>
+
+ <receiver
+ android:name=".AppWidget"
+ android:exported="true"
+ android:label="@string/label" >
+ <intent-filter>
+ <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+ </intent-filter>
+
+ <meta-data
+ android:name="android.appwidget.provider"
+ android:resource="@xml/config" />
+ </receiver>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice1.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice1.xml
new file mode 100644
index 0000000..67e519f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice1.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <service
+ android:exported="true"
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass"
+ android:process=":remote" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </service>
+ </application>
+
+</manifest>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice2.xml
new file mode 100644
index 0000000..491a14f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice2.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <service
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass"
+ android:process=":remote" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </service>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice3.xml
new file mode 100644
index 0000000..8d5f166
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice3.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <service
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass"
+ android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
+ android:process=":remote" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </service>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice4.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice4.xml
new file mode 100644
index 0000000..f952225
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice4.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
+ android:label="@string/app_name" >
+ <service
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass"
+ android:process=":remote" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </service>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice5.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice5.xml
new file mode 100644
index 0000000..c9b9a78
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/exportservice5.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <service
+ android:label="@string/app_name"
+ android:name="com.sample.service.serviceClass"
+ android:process=":remote" >
+ <intent-filter >
+ <action android:name="com.sample.service.serviceClass" >
+ </action>
+ </intent-filter>
+ </service>
+ </application>
+
+</manifest>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/gen/my/pkg/R.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/gen/my/pkg/R.java.txt
new file mode 100644
index 0000000..fad43bf
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/gen/my/pkg/R.java.txt
@@ -0,0 +1,23 @@
+public final class R {
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int ic_launcher=0x7f020000;
+ }
+ public static final class id {
+ public static final int button1=0x7f050000;
+ public static final int button2=0x7f050004;
+ public static final int imageView1=0x7f050003;
+ public static final int include1=0x7f050005;
+ public static final int linearLayout1=0x7f050001;
+ public static final int linearLayout2=0x7f050002;
+ }
+ public static final class layout {
+ public static final int main=0x7f030000;
+ public static final int other=0x7f030001;
+ }
+ public static final class string {
+ public static final int app_name=0x7f040001;
+ public static final int hello=0x7f040000;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/gen/my/pkg/R2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/gen/my/pkg/R2.java.txt
new file mode 100644
index 0000000..ed8fd7d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/gen/my/pkg/R2.java.txt
@@ -0,0 +1,5 @@
+public final class R {
+ public static final class drawable {
+ public static final int ic_menu_help=0x7f020000;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/grantpermission.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/grantpermission.xml
new file mode 100644
index 0000000..e07c370
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/grantpermission.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity"
+ android:permission="Foo" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <!-- good: -->
+ <grant-uri-permission android:pathPrefix="/all_downloads/"/>
+ <!-- bad: -->
+ <grant-uri-permission android:path="/"/>
+ <grant-uri-permission android:pathPrefix="/"/>
+ <grant-uri-permission android:pathPattern=".*"/>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/ignoremissing.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/ignoremissing.xml
new file mode 100644
index 0000000..99d804e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/ignoremissing.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+ <issue id="IconDensities" severity="warning">
+ <ignore path="res/drawable-hdpi" />
+ </issue>
+</lint>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/minsdk5targetsdk14.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/minsdk5targetsdk14.xml
new file mode 100644
index 0000000..482b7fa
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/minsdk5targetsdk14.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="5" android:targetSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/minsdk5targetsdk9.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/minsdk5targetsdk9.xml
new file mode 100644
index 0000000..1cc7596
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/minsdk5targetsdk9.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="5" android:targetSdkVersion="9" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/missingmin.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/missingmin.xml
new file mode 100644
index 0000000..19b3d0a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/missingmin.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:targetSdkVersion="10" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/missingprefix.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/missingprefix.xml
new file mode 100644
index 0000000..2bb6824
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/missingprefix.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android.label="@string/app_name" >
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/missingtarget.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/missingtarget.xml
new file mode 100644
index 0000000..1f4fba0
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/missingtarget.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="10" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/missingusessdk.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/missingusessdk.xml
new file mode 100644
index 0000000..00c0167
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/missingusessdk.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiplesdk.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiplesdk.xml
new file mode 100644
index 0000000..950cf4d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiplesdk.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="5" />
+ <uses-sdk android:targetSdkVersion="14" />
+ <uses-sdk android:maxSdkVersion="15" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/LibraryCode.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/LibraryCode.java.txt
new file mode 100644
index 0000000..25a9d75
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/LibraryCode.java.txt
@@ -0,0 +1,7 @@
+package foo.library;
+
+public class LibraryCode {
+ static {
+ System.out.println(R.string.string1);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/MainCode.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/MainCode.java.txt
new file mode 100644
index 0000000..7955e6b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/MainCode.java.txt
@@ -0,0 +1,7 @@
+package foo.main;
+
+public class MainCode {
+ static {
+ System.out.println(R.string.string2);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/library-manifest.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/library-manifest.xml
new file mode 100644
index 0000000..ed6e65b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/library-manifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.library"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".LibraryProjectActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <!-- Dummy string references for unused resource check -->
+ <meta-data
+ android:name="com.google.android.backup.api_key"
+ android:value="@string/string3" />
+ <meta-data
+ android:name="foo"
+ android:value="@string/string1" />
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/library.properties b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/library.properties
new file mode 100644
index 0000000..d525577
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/library.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-14
+android.library=true
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/main-manifest.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/main-manifest.xml
new file mode 100644
index 0000000..5c50721
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/main-manifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.master"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".MasterProjectActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/main-merge.properties b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/main-merge.properties
new file mode 100644
index 0000000..f1b8f95
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/main-merge.properties
@@ -0,0 +1,13 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-14
+manifestmerger.enabled=true
+android.library.reference.1=../LibraryProject
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/main.properties b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/main.properties
new file mode 100644
index 0000000..f366140
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/main.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-14
+android.library.reference.1=../LibraryProject
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/strings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/strings.xml
new file mode 100644
index 0000000..f53e15f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/multiproject/strings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">LibraryProject</string>
+ <string name="string1">String 1</string>
+ <string name="string2">String 2</string>
+ <string name="string3">String 3</string>
+
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/oldtarget.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/oldtarget.xml
new file mode 100644
index 0000000..d72d7fc
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/oldtarget.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.bytecode"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="14" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".BytecodeTestsActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/.classpath b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/.classpath
new file mode 100644
index 0000000..a4763d1
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/.project b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/.project
new file mode 100644
index 0000000..5479f13
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>overdraw</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/AndroidManifest.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/AndroidManifest.xml
new file mode 100644
index 0000000..c9c6127
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.pkg"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="10" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/MyTheme" >
+ <activity
+ android:name=".OverdrawActivity"
+ android:label="@string/app_name"
+ android:theme="@style/MyTheme.First" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".SecondActivity"
+ android:label="@string/app_name" >
+ </activity>
+ <activity
+ android:name=".ThirdActivity"
+ android:label="@string/app_name" >
+ </activity>
+ <activity
+ android:name="test.pkg.FourthActivity"
+ android:label="@string/app_name"
+ android:theme="@style/MyTheme.Fourth" >
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/gen/test/pkg/BuildConfig.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/gen/test/pkg/BuildConfig.java.txt
new file mode 100644
index 0000000..57e2a0e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/gen/test/pkg/BuildConfig.java.txt
@@ -0,0 +1,6 @@
+/** Automatically generated file. DO NOT MODIFY */
+package test.pkg;
+
+public final class BuildConfig {
+ public final static boolean DEBUG = true;
+} \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/gen/test/pkg/R.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/gen/test/pkg/R.java.txt
new file mode 100644
index 0000000..c7900de
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/gen/test/pkg/R.java.txt
@@ -0,0 +1,34 @@
+/* AUTO-GENERATED FILE. DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found. It
+ * should not be modified by hand.
+ */
+
+package test.pkg;
+
+public final class R {
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int ic_launcher=0x7f020000;
+ }
+ public static final class layout {
+ public static final int fifth=0x7f030000;
+ public static final int fourth=0x7f030001;
+ public static final int main=0x7f030002;
+ public static final int second=0x7f030003;
+ public static final int third=0x7f030004;
+ }
+ public static final class string {
+ public static final int app_name=0x7f040001;
+ public static final int hello=0x7f040000;
+ }
+ public static final class style {
+ public static final int MyTheme=0x7f050000;
+ public static final int MyTheme_First=0x7f050001;
+ public static final int MyTheme_Fourth=0x7f050004;
+ public static final int MyTheme_Second=0x7f050002;
+ public static final int MyTheme_Third=0x7f050003;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/project.properties b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/project.properties
new file mode 100644
index 0000000..f049142
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/project.properties
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-10
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable-hdpi/ic_launcher.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable-ldpi/ic_launcher.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..1095584
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable-mdpi/ic_launcher.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable/custombg.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable/custombg.xml
new file mode 100644
index 0000000..a8e70d4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable/custombg.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<bitmap
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_launcher"
+ android:tileMode="clamp" /> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable/custombg2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable/custombg2.xml
new file mode 100644
index 0000000..47513c3
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/drawable/custombg2.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/ic_launcher" />
+</selector>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/fifth.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/fifth.xml
new file mode 100644
index 0000000..00a5c25
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/fifth.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/custombg2"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hello" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/fourth.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/fourth.xml
new file mode 100644
index 0000000..3102f2c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/fourth.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/ic_launcher"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hello" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/main.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/main.xml
new file mode 100644
index 0000000..3102f2c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/main.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/ic_launcher"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hello" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/main_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/main_ignore.xml
new file mode 100644
index 0000000..63f0fd3
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/main_ignore.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/ic_launcher"
+ tools:ignore="Overdraw"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hello" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/second.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/second.xml
new file mode 100644
index 0000000..3102f2c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/second.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/ic_launcher"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hello" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/sixth.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/sixth.xml
new file mode 100644
index 0000000..7f17c9e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/sixth.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:background="@drawable/custombg"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hello" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/third.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/third.xml
new file mode 100644
index 0000000..3102f2c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/layout/third.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/ic_launcher"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hello" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/values/strings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/values/strings.xml
new file mode 100644
index 0000000..bb302bc
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="hello">Hello World, OverdrawActivity!</string>
+ <string name="app_name">Overdraw</string>
+
+</resources> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/values/styles.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/values/styles.xml
new file mode 100644
index 0000000..5ab6ad6
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/res/values/styles.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <style name="MyTheme" parent="@android:style/Theme.Light">
+ <item name="android:windowBackground">@drawable/ic_launcher</item>
+ </style>
+
+ <style name="MyTheme.First">
+ <item name="android:textColor">#ff00ff00</item>
+ </style>
+
+ <style name="MyTheme.Second">
+ <item name="android:windowIsTranslucent">true</item>
+ </style>
+
+ <style name="MyTheme.Third">
+ <item name="android:textColor">#ff000000</item>
+ </style>
+
+ <style name="MyTheme.Fourth">
+ <item name="android:windowBackground">@null</item>
+ <item name="android:textColor">#ff000000</item>
+ </style>
+
+</resources> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/FourthActivity.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/FourthActivity.java.txt
new file mode 100644
index 0000000..04fac3f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/FourthActivity.java.txt
@@ -0,0 +1,13 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class FourthActivity extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.fourth);
+ }
+} \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/OverdrawActivity.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/OverdrawActivity.java.txt
new file mode 100644
index 0000000..8779c19
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/OverdrawActivity.java.txt
@@ -0,0 +1,13 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class OverdrawActivity extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+} \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/SecondActivity.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/SecondActivity.java.txt
new file mode 100644
index 0000000..52b7ca0
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/SecondActivity.java.txt
@@ -0,0 +1,13 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class SecondActivity extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.second);
+ }
+} \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/ThirdActivity.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/ThirdActivity.java.txt
new file mode 100644
index 0000000..3d4da95
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/overdraw/src/test/pkg/ThirdActivity.java.txt
@@ -0,0 +1,14 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class ThirdActivity extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setTheme(R.style.MyTheme_Third);
+ setContentView(R.layout.third);
+ }
+} \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/proguard.cfg b/lint/cli/src/test/java/com/android/tools/lint/checks/data/proguard.cfg
new file mode 100644
index 0000000..12dd039
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/proguard.cfg
@@ -0,0 +1,36 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+-keepclasseswithmembernames class * {
+ public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/proguard.pro b/lint/cli/src/test/java/com/android/tools/lint/checks/data/proguard.pro
new file mode 100644
index 0000000..53f41fe
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/proguard.pro
@@ -0,0 +1,64 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-verbose
+-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
+-allowaccessmodification
+-keepattributes *Annotation*
+
+
+# dex does not like code run through proguard optimize and preverify steps.
+-dontoptimize
+-dontpreverify
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgent
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+-keep public class * extends android.view.View {
+ public <init>(android.content.Context);
+ public <init>(android.content.Context, android.util.AttributeSet);
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+ public void set*(...);
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.app.Activity {
+ public void *(android.view.View);
+}
+
+# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
+
+-keepclassmembers class **.R$* {
+ public static <fields>;
+}
+
+# The support library contains references to newer platform versions.
+# Don't warn about those in case this app is linking against an older
+# platform version. We know about them, and they are safe.
+-dontwarn android.support.**
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/proguard.properties b/lint/cli/src/test/java/com/android/tools/lint/checks/data/proguard.properties
new file mode 100644
index 0000000..989c3c7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/proguard.properties
@@ -0,0 +1,2 @@
+target=android-14
+proguard.config=${sdk.dir}/foo.cfg:${user.home}/bar.pro;myfile.txt
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties1 b/lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties1
new file mode 100644
index 0000000..2b783dd
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties1
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this:
+#proguard.config=proguard.cfg
+
+# Project target.
+target=android-3
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties2 b/lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties2
new file mode 100644
index 0000000..d9a28ec
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties2
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this:
+proguard.config=proguard.cfg
+
+# Project target.
+target=android-3
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties3 b/lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties3
new file mode 100644
index 0000000..3cb9d31
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties3
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-3
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties4 b/lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties4
new file mode 100644
index 0000000..fca9311
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/project.properties4
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this:
+proguard.config=${sdk.dir}/tools/proguard/android-defaults.pro:proguard.pro
+
+# Project target.
+target=android-3
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/protectedpermissions.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/protectedpermissions.xml
new file mode 100644
index 0000000..8b62497
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/protectedpermissions.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <!-- No warnings for those -->
+ <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <!-- Warnings for those -->
+ <uses-permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE" />
+ <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
+ <uses-permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES" />
+ <uses-permission android:name="android.permission.ACCESS_MTP" />
+ <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
+ <uses-permission android:name="android.permission.ACCOUNT_MANAGER" />
+ <uses-permission android:name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK" />
+ <uses-permission android:name="android.permission.ASEC_ACCESS" />
+ <uses-permission android:name="android.permission.ASEC_CREATE" />
+ <uses-permission android:name="android.permission.ASEC_DESTROY" />
+ <uses-permission android:name="android.permission.ASEC_MOUNT_UNMOUNT" />
+ <uses-permission android:name="android.permission.ASEC_RENAME" />
+ <uses-permission android:name="android.permission.BACKUP" />
+ <uses-permission android:name="android.permission.BIND_APPWIDGET" />
+ <uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" />
+ <uses-permission android:name="android.permission.BIND_INPUT_METHOD" />
+ <uses-permission android:name="android.permission.BIND_PACKAGE_VERIFIER" />
+ <uses-permission android:name="android.permission.BIND_REMOTEVIEWS" />
+ <uses-permission android:name="android.permission.BIND_TEXT_SERVICE" />
+ <uses-permission android:name="android.permission.BIND_VPN_SERVICE" />
+ <uses-permission android:name="android.permission.BIND_WALLPAPER" />
+ <uses-permission android:name="android.permission.BRICK" />
+ <uses-permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED" />
+ <uses-permission android:name="android.permission.BROADCAST_SMS" />
+ <uses-permission android:name="android.permission.BROADCAST_WAP_PUSH" />
+ <uses-permission android:name="android.permission.CALL_PRIVILEGED" />
+ <uses-permission android:name="android.permission.CHANGE_BACKGROUND_DATA_SETTING" />
+ <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
+ <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
+ <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP" />
+ <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+ <uses-permission android:name="android.permission.CONTROL_LOCATION_UPDATES" />
+ <uses-permission android:name="android.permission.COPY_PROTECTED_DATA" />
+ <uses-permission android:name="android.permission.CRYPT_KEEPER" />
+ <uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
+ <uses-permission android:name="android.permission.DELETE_PACKAGES" />
+ <uses-permission android:name="android.permission.DEVICE_POWER" />
+ <uses-permission android:name="android.permission.DIAGNOSTIC" />
+ <uses-permission android:name="android.permission.DUMP" />
+ <uses-permission android:name="android.permission.FACTORY_TEST" />
+ <uses-permission android:name="android.permission.FORCE_BACK" />
+ <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" />
+ <uses-permission android:name="android.permission.GLOBAL_SEARCH" />
+ <uses-permission android:name="android.permission.GLOBAL_SEARCH_CONTROL" />
+ <uses-permission android:name="android.permission.HARDWARE_TEST" />
+ <uses-permission android:name="android.permission.INJECT_EVENTS" />
+ <uses-permission android:name="android.permission.INSTALL_LOCATION_PROVIDER" />
+ <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
+ <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
+ <uses-permission android:name="android.permission.MANAGE_APP_TOKENS" />
+ <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
+ <uses-permission android:name="android.permission.MANAGE_USB" />
+ <uses-permission android:name="android.permission.MASTER_CLEAR" />
+ <uses-permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING" />
+ <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+ <uses-permission android:name="android.permission.MOVE_PACKAGE" />
+ <uses-permission android:name="android.permission.NET_ADMIN" />
+ <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+ <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+ <uses-permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT" />
+ <uses-permission android:name="android.permission.PERFORM_CDMA_PROVISIONING" />
+ <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
+ <uses-permission android:name="android.permission.READ_INPUT_STATE" />
+ <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
+ <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+ <uses-permission android:name="android.permission.REBOOT" />
+ <uses-permission android:name="android.permission.RECEIVE_EMERGENCY_BROADCAST" />
+ <uses-permission android:name="android.permission.REMOVE_TASKS" />
+ <uses-permission android:name="android.permission.RETRIEVE_WINDOW_CONTENT" />
+ <uses-permission android:name="android.permission.SEND_SMS_NO_CONFIRMATION" />
+ <uses-permission android:name="android.permission.SET_ACTIVITY_WATCHER" />
+ <uses-permission android:name="android.permission.SET_ORIENTATION" />
+ <uses-permission android:name="android.permission.SET_POINTER_SPEED" />
+ <uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS" />
+ <uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" />
+ <uses-permission android:name="android.permission.SET_TIME" />
+ <uses-permission android:name="android.permission.SET_WALLPAPER_COMPONENT" />
+ <uses-permission android:name="android.permission.SHUTDOWN" />
+ <uses-permission android:name="android.permission.STATUS_BAR" />
+ <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
+ <uses-permission android:name="android.permission.STOP_APP_SWITCHES" />
+ <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
+ <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
+ <uses-permission android:name="android.permission.WRITE_GSERVICES" />
+ <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/protectedpermissions2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/protectedpermissions2.xml
new file mode 100644
index 0000000..d3b88da
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/protectedpermissions2.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <!-- No warnings for these: -->
+ <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <!-- Warnings for these: -->
+ <uses-permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE" tools:ignore="ProtectedPermissions" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifest.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifest.xml
new file mode 100644
index 0000000..0b07cdf
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.pkg"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="8"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".Foo$Bar"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".Foo$Baz"
+ android:label="@string/app_name" >
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifestInner.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifestInner.xml
new file mode 100644
index 0000000..1b87d9d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifestInner.xml
@@ -0,0 +1,25 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.pkg.Foo"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="8"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".Bar"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifestWrong.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifestWrong.xml
new file mode 100644
index 0000000..bfdcde0
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifestWrong.xml
@@ -0,0 +1,25 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.pkg.Foo"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="8"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="test.pkg.Foo.Bar"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifestWrong2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifestWrong2.xml
new file mode 100644
index 0000000..8773e0f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/AndroidManifestWrong2.xml
@@ -0,0 +1,25 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.pkg"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="8"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".Foo.Bar"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Bar.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Bar.class.data
new file mode 100644
index 0000000..e51a0e8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Bar.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Bar.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Bar.java.txt
new file mode 100644
index 0000000..b514f11
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Bar.java.txt
@@ -0,0 +1,8 @@
+package test.pkg.Foo;
+
+import android.app.Activity;
+
+public class Bar extends Activity {
+ private Bar() {
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo$Bar.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo$Bar.class.data
new file mode 100644
index 0000000..da45ebb
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo$Bar.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo$Baz.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo$Baz.class.data
new file mode 100644
index 0000000..aadd767
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo$Baz.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo.class.data
new file mode 100644
index 0000000..aafcc73
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo.class.data
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo.java.txt
new file mode 100644
index 0000000..a647030
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo.java.txt
@@ -0,0 +1,10 @@
+package test.pkg;
+
+import android.app.Activity;
+
+public class Foo {
+ public static class Bar extends Activity {
+ }
+ public class Baz extends Activity {
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/appwidget_bg.9.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/appwidget_bg.9.png
new file mode 100644
index 0000000..d9af8fb
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/appwidget_bg.9.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/appwidget_bg_focus.9.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/appwidget_bg_focus.9.png
new file mode 100644
index 0000000..ee098af
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/appwidget_bg_focus.9.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/filled.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/filled.png
new file mode 100644
index 0000000..59fd90a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/filled.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/ic_launcher.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/other.9.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/other.9.png
new file mode 100644
index 0000000..d9af8fb
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/other.9.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/unrelated.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/unrelated.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-hdpi/unrelated.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/frame.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/frame.png
new file mode 100644
index 0000000..840b2c2
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/frame.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/ic_menu_add_clip_normal.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/ic_menu_add_clip_normal.png
new file mode 100644
index 0000000..26f5afe
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/ic_menu_add_clip_normal.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/sample_icon.gif b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/sample_icon.gif
new file mode 100644
index 0000000..1a0be94
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/sample_icon.gif
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/sample_icon.jpg b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/sample_icon.jpg
new file mode 100644
index 0000000..f872487
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/sample_icon.jpg
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/stat_notify_alarm.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/stat_notify_alarm.png
new file mode 100644
index 0000000..c61626c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-mdpi/stat_notify_alarm.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-nodpi/frame.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-nodpi/frame.png
new file mode 100644
index 0000000..840b2c2
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-nodpi/frame.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-xlarge-nodpi-v11/frame.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-xlarge-nodpi-v11/frame.png
new file mode 100644
index 0000000..840b2c2
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable-xlarge-nodpi-v11/frame.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/ic_launcher.png b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/ic_launcher.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/ic_launcher.png
Binary files differ
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/ic_menu_help.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/ic_menu_help.xml
new file mode 100644
index 0000000..41f840f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/ic_menu_help.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:src="@android:drawable/ic_menu_help"
+ tools:ignore="UnusedResources" />
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/states.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/states.xml
new file mode 100644
index 0000000..3dedb64
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/states.xml
@@ -0,0 +1,7 @@
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="#ff000000"/> <!-- WRONG, SHOULD BE LAST -->
+ <item android:state_pressed="true"
+ android:color="#ffff0000"/> <!-- pressed -->
+ <item android:state_focused="true"
+ android:color="#ff0000ff"/> <!-- focused -->
+</selector>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/states2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/states2.xml
new file mode 100644
index 0000000..dac176d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/states2.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res/com.domain.pkg">
+<item
+ app:mystate_custom="false"
+ android:drawable="@drawable/item" />
+</selector>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/states3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/states3.xml
new file mode 100644
index 0000000..c3fc533
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/drawable/states3.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_checked="false" android:state_window_focused="false"
+ android:drawable="@drawable/btn_star_big_off" />
+ <item android:state_checked="true" android:state_window_focused="false"
+ android:drawable="@drawable/btn_star_big_on" />
+ <item android:state_checked="true" android:state_window_focused="false"
+ android:state_enabled="false" android:drawable="@drawable/btn_star_big_on_disable" />
+ <item android:state_checked="false" android:state_window_focused="false"
+ android:state_enabled="false" android:drawable="@drawable/btn_star_big_off_disable" />
+
+ <item android:state_checked="true" android:state_pressed="true"
+ android:drawable="@drawable/btn_star_big_on_pressed" />
+ <item android:state_checked="false" android:state_pressed="true"
+ android:drawable="@drawable/btn_star_big_off_pressed" />
+
+ <item android:state_checked="true" android:state_focused="true"
+ android:drawable="@drawable/btn_star_big_on_selected" />
+ <item android:state_checked="false" android:state_focused="true"
+ android:drawable="@drawable/btn_star_big_off_selected" />
+
+ <item android:state_checked="true" android:state_focused="true" android:state_enabled="false"
+ android:drawable="@drawable/btn_star_big_on_disable_focused" />
+ <item android:state_checked="true" android:state_focused="false" android:state_enabled="false"
+ android:drawable="@drawable/btn_star_big_on_disable" />
+
+ <item android:state_checked="false" android:state_focused="true" android:state_enabled="false"
+ android:drawable="@drawable/btn_star_big_off_disable_focused" />
+ <item android:state_checked="false" android:state_focused="false" android:state_enabled="false"
+ android:drawable="@drawable/btn_star_big_off_disable" />
+
+ <item android:state_checked="false" android:drawable="@drawable/btn_star_big_off" />
+ <item android:state_checked="true" android:drawable="@drawable/btn_star_big_on" />
+</selector> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/accessibility.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/accessibility.xml
new file mode 100644
index 0000000..c00a880
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/accessibility.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/newlinear" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
+ <Button android:text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
+ <ImageView android:id="@+id/android_logo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
+ <ImageButton android:importantForAccessibility="yes" android:id="@+id/android_logo2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
+ <Button android:text="Button" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
+ <Button android:id="@+android:id/summary" android:contentDescription="@string/label" />
+ <ImageButton android:importantForAccessibility="no" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/accessibility2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/accessibility2.xml
new file mode 100644
index 0000000..3f45c26
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/accessibility2.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/newlinear" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
+ <Button android:text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
+ <ImageView android:id="@+id/android_logo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
+ <ImageButton android:importantForAccessibility="yes" android:id="@+id/android_logo2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
+ <Button android:text="Button" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
+ <Button android:id="@+android:id/summary" android:contentDescription="@string/label" />
+ <ImageButton android:importantForAccessibility="no" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
+ <EditText android:hint="@string/label" android:id="@+android:id/summary" android:contentDescription="@string/label" />
+ <EditText android:id="@+android:id/summary" android:contentDescription="@string/label" />
+ <EditText tools:ignore="ContentDescription" android:hint="@string/label" android:id="@+android:id/summary" android:contentDescription="@string/label" />
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/activity_item_two_pane.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/activity_item_two_pane.xml
new file mode 100644
index 0000000..b19047a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/activity_item_two_pane.xml
@@ -0,0 +1,37 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:divider="?android:attr/dividerHorizontal"
+ android:orientation="horizontal"
+ android:showDividers="middle"
+ tools:context=".ItemListActivity" >
+
+ <!--
+ This layout is a two-pane layout for the Items
+ master/detail flow. See res/values-large/refs.xml and
+ res/values-sw600dp/refs.xml for an example of layout aliases
+ that replace the single-pane version of the layout with
+ this two-pane version.
+
+ For more on layout aliases, see:
+ http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters
+ -->
+
+ <fragment
+ android:id="@+id/item_list"
+ android:name="com.example.master.ItemListFragment"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ tools:layout="@android:layout/list_content" />
+
+ <FrameLayout
+ android:id="@+id/item_detail_container"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="3" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/baseline_weights.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/baseline_weights.xml
new file mode 100644
index 0000000..fa5a39a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/baseline_weights.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal" >
+
+ <LinearLayout
+ android:id="@+id/linearLayout1"
+ android:layout_weight="0.3"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+ </LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/frameLayout1"
+ android:layout_weight="0.7"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ </FrameLayout>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/baseline_weights2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/baseline_weights2.xml
new file mode 100644
index 0000000..2e4af6b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/baseline_weights2.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:id="@+id/linearLayout1"
+ android:layout_weight="0.3"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+ </LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/frameLayout1"
+ android:layout_weight="0.7"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ </FrameLayout>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/baseline_weights3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/baseline_weights3.xml
new file mode 100644
index 0000000..079bd24
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/baseline_weights3.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <LinearLayout
+ android:id="@+id/linearLayout1"
+ android:layout_weight="0.3"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+ </LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/frameLayout1"
+ android:layout_weight="0.7"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ </FrameLayout>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/breadcrumbs_in_fragment.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/breadcrumbs_in_fragment.xml
new file mode 100644
index 0000000..5e8824a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/breadcrumbs_in_fragment.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="0dip"
+ android:layout_height="0dip"
+ android:visibility="gone" />
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/broken.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/broken.xml
new file mode 100644
index 0000000..5dd9d2d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/broken.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/newlinear" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
+ <Button android:text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
+ <ImageView android:id="@+id/android_logo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
+ ImageButton android:id="@+id/android_logo2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
+ <Button android:text="Button" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
+ <Button android:id="@+android:id/summary" android:contentDescription="@string/label" />
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar.xml
new file mode 100644
index 0000000..d02d49b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar.xml
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <!-- Hardcoded strings, wrong order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="OK" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Cancel" />
+ </LinearLayout>
+
+ <!-- Hardcoded strings, right order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Cancel" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="OK" />
+ </LinearLayout>
+
+ <!-- @android:string resources, wrong order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@android:string/ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@android:string/cancel" />
+ </LinearLayout>
+
+ <!-- @android:string resources, right order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@android:string/cancel" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@android:string/ok" />
+ </LinearLayout>
+
+ <!-- @string/ok/cancel resources, right order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/cancel" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/ok" />
+ </LinearLayout>
+
+ <!-- @string/ok/cancel resources, wrong order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/cancel" />
+ </LinearLayout>
+
+ <!-- Random name resources, right order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/giveup" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/resume" />
+ </LinearLayout>
+
+ <!-- Random name resources, wrong order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/resume" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/giveup" />
+ </LinearLayout>
+
+ <!-- Random name resources with varying case, wrong order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/resume2" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/giveup2" />
+ </LinearLayout>
+
+ <!-- Resources with only one of OK and Cancel, wrong order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/abort" />
+ </LinearLayout>
+
+ <!-- Resources with only one of OK and Cancel, wrong order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:layout_width="wrap_content" android:background="?android:attr/selectableItemBackground"
+ android:layout_height="wrap_content"
+ android:text="@string/send" />
+
+ <Button
+ android:layout_width="wrap_content" android:background="?android:attr/selectableItemBackground"
+ android:layout_height="wrap_content"
+ android:text="@string/cancel" />
+ </LinearLayout>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/goback" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar2.xml
new file mode 100644
index 0000000..f6ae19b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar2.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <ProgressBar
+ android:id="@+id/loading_progress"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginBottom="60dip"
+ android:layout_marginLeft="40dip"
+ android:layout_marginTop="40dip"
+ android:max="10000" />
+
+ <TextView
+ android:id="@+id/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_alignWithParentIfMissing="true"
+ android:layout_marginBottom="60dip"
+ android:layout_marginLeft="40dip"
+ android:layout_marginTop="40dip"
+ android:layout_toRightOf="@id/loading_progress"
+ android:ellipsize="end"
+ android:maxLines="3"
+ android:paddingRight="120dip"
+ android:text="@string/creating_instant_mix"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <Button
+ android:id="@+id/cancel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignRight="@id/text"
+ android:layout_below="@id/text"
+ android:background="@null"
+ android:text="@string/cancel" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_above="@id/cancel"
+ android:layout_alignLeft="@id/cancel"
+ android:layout_alignRight="@id/cancel"
+ android:scaleType="fitXY"
+ android:src="@drawable/menu_list_divider" />
+
+</RelativeLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar3.xml
new file mode 100644
index 0000000..8dbcb10
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar3.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:text="@string/weekpicker_title"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#ffffff"
+ android:padding="6dip" >
+
+ <Button
+ android:id="@+id/set"
+ android:layout_width="120dip"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:text="@string/weekpicker_set" />
+
+ <Button
+ android:id="@+id/cancel"
+ android:layout_width="120dip"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:text="@string/cancel" />
+ </RelativeLayout>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar4.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar4.xml
new file mode 100644
index 0000000..9fe69d5
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar4.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone" >
+
+ <RatingBar
+ android:id="@+id/review_form_rating"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:numStars="5"
+ android:stepSize="1" />
+
+ <EditText
+ android:id="@+id/review_form_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_toLeftOf="@id/review_form_rating"
+ android:hint="@string/review_form_title_hint"
+ android:inputType="text|textCapSentences|textAutoCorrect"
+ android:lines="1" />
+
+ <EditText
+ android:id="@+id/review_form_review"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/review_form_title"
+ android:gravity="top"
+ android:hint="@string/review_form_content_hint"
+ android:inputType="text|textCapSentences|textAutoCorrect|textMultiLine"
+ android:minLines="3"
+ android:singleLine="false"
+ android:visibility="gone" />
+
+ <Button
+ android:id="@+id/review_form_submit"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_below="@id/review_form_review"
+ android:text="@string/submit"
+ android:visibility="gone" />
+
+ <Button
+ android:id="@+id/review_form_cancel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/review_form_review"
+ android:layout_toLeftOf="@id/review_form_submit"
+ android:text="@string/cancel"
+ android:visibility="gone" />
+
+</RelativeLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar_suppressed.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar_suppressed.xml
new file mode 100644
index 0000000..a03824d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/buttonbar_suppressed.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <!-- Hardcoded strings, wrong order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="OK"
+ tools:ignore="ButtonOrder" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Cancel"
+ tools:ignore="ButtonOrder" />
+ </LinearLayout>
+
+ <!-- @android:string resources, wrong order -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ tools:ignore="ButtonOrder" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@android:string/ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@android:string/cancel" />
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts.xml
new file mode 100644
index 0000000..40f01ed
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <Button
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <EditText
+ android:id="@+id/edittext"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="EditText" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts2.xml
new file mode 100644
index 0000000..249c02f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts2.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- unit test from issue 27441 -->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <RadioGroup
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <RadioButton
+ android:id="@+id/additional"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <Spinner
+ android:id="@+id/reminder_lead"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </RadioGroup>
+
+</ScrollView>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts3.xml
new file mode 100644
index 0000000..990e5f0
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts3.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <RadioButton
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <EditText
+ android:id="@+id/edittext"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="EditText" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts4.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts4.xml
new file mode 100644
index 0000000..371964e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/casts4.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <ToggleButton
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <EditText
+ android:id="@+id/edittext"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="EditText" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/compound.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/compound.xml
new file mode 100644
index 0000000..f7b28ef
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/compound.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/compound2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/compound2.xml
new file mode 100644
index 0000000..24f45dc
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/compound2.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="@android:drawable/ic_dialog_alert"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/compound3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/compound3.xml
new file mode 100644
index 0000000..68d42fa
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/compound3.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="fitStart" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/crcrlf.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/crcrlf.xml
new file mode 100644
index 0000000..d029725
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/crcrlf.xml
@@ -0,0 +1,14 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:text="Hello"
+ tools:context=".MainActivity" />
+
+</RelativeLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/crcrlf_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/crcrlf_ignore.xml
new file mode 100644
index 0000000..680a765
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/crcrlf_ignore.xml
@@ -0,0 +1,19 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:ignore="MangledCRLF" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:text="@string/app_name"
+ tools:context=".MainActivity" />
+
+
+
+
+
+</RelativeLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/customattrlayout.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/customattrlayout.xml
new file mode 100644
index 0000000..b4c49f0
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/customattrlayout.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<foo.bar.ContentFrame
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:foobar="http://schemas.android.com/apk/res/foo.bar"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ foobar:contentId="@+id/test" />
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/customview.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/customview.xml
new file mode 100644
index 0000000..976d636
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/customview.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:other="http://schemas.foo.bar.com/other"
+ xmlns:foo="http://schemas.android.com/apk/res/foo"
+ android:id="@+id/newlinear"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <foo.bar.Baz
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button1"
+ foo:misc="Custom attribute"
+ tools:ignore="HardcodedText" >
+ </foo.bar.Baz>
+
+ <!-- Wrong namespace uri prefix: Don't warn -->
+ <foo.bar.Baz
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button1"
+ other:misc="Custom attribute"
+ tools:ignore="HardcodedText" >
+ </foo.bar.Baz>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/customview2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/customview2.xml
new file mode 100644
index 0000000..fcd43e6
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/customview2.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:other="http://schemas.foo.bar.com/other"
+ xmlns:foo="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/newlinear"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <foo.bar.Baz
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button1"
+ foo:misc="Custom attribute"
+ tools:ignore="HardcodedText" >
+ </foo.bar.Baz>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/default_item_badges.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/default_item_badges.xml
new file mode 100644
index 0000000..082a520
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/default_item_badges.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/video_badges"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/deprecation.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/deprecation.xml
new file mode 100644
index 0000000..70b7f23
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/deprecation.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_x="5dp"
+ android:layout_y="100dp"
+ android:text="Button" />
+
+ <!-- Deprecated attributes -->
+ <TextView
+ android:autoText="true"
+ android:capitalize="true"
+ android:editable="true"
+ android:enabled="true"
+ android:inputMethod="@+id/foo"
+ android:numeric="true"
+ android:password="true"
+ android:phoneNumber="true"
+ android:singleLine="true" />
+
+ <EditText android:editable="true" />
+ <EditText android:editable="false" />
+
+</AbsoluteLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/detailed_item.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/detailed_item.xml
new file mode 100644
index 0000000..a5d4226
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/detailed_item.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/video_badges" />
+
+</RelativeLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/duplicate.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/duplicate.xml
new file mode 100644
index 0000000..e142e9e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/duplicate.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/newlinear" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
+ <Button android:text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
+ <ImageView android:id="@+id/android_logo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
+ <ImageButton android:id="@+id/android_logo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
+ <Button android:text="Button" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
+</LinearLayout>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/edit_textview.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/edit_textview.xml
new file mode 100644
index 0000000..c0d8cda
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/edit_textview.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <!-- Various attributes that should be set on EditTexts, not TextViews -->
+
+ <TextView
+ android:text="label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:autoText="true"
+ android:bufferType="editable"
+ android:capitalize="words"
+ android:cursorVisible="true"
+ android:digits=""
+ android:editable="true"
+ android:editorExtras="@+id/foobar"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:imeActionId="@+id/foo"
+ android:imeActionLabel=""
+ android:imeOptions=""
+ android:inputMethod=""
+ android:inputType="text"
+ android:numeric=""
+ android:password="true"
+ android:phoneNumber="true"
+ android:privateImeOptions="" />
+
+ <!-- Various attributes that should be set on EditTexts, not Buttons -->
+
+ <Button
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:cursorVisible="true" />
+
+ <CheckedTextView
+ android:id="@+id/checkedTextView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:cursorVisible="true" />
+
+ <CheckBox
+ android:id="@+id/checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:cursorVisible="true" />
+
+ <RadioButton
+ android:id="@+id/radioButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:cursorVisible="true" />
+
+ <ToggleButton
+ android:id="@+id/toggleButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:cursorVisible="true" />
+
+
+ <!-- Ok #1 -->
+
+ <TextView
+ android:text="label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:bufferType="spannable"
+ android:freezesText="true"
+ android:editable="false"
+ android:inputType="none" />
+
+ <!-- Ok #2 -->
+
+ <TextView
+ android:text="label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:id="@+id/dynamictext"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:id="@+id/dynamictext"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textIsSelectable="true" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/edit_type.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/edit_type.xml
new file mode 100644
index 0000000..8f8cf90
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/edit_type.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <!-- Wrong: doesn't specify textPassword -->
+
+ <EditText
+ android:id="@+id/mypassword"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="text" >
+
+ <requestFocus />
+ </EditText>
+
+ <!-- OK, specifies textPassword: -->
+
+ <EditText
+ android:id="@+id/password1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="text|numberPassword" />
+
+ <!-- OK, specifies password: -->
+
+ <EditText
+ android:id="@+id/password2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="text"
+ android:password="true" />
+
+ <!-- Wrong, doesn't include number -->
+
+ <EditText
+ android:id="@+id/password_length"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="text" />
+
+ <!-- Wrong, doesn't include URL -->
+
+ <EditText
+ android:id="@+id/welcome_url"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="text" />
+
+ <!-- Wrong, doesn't include date -->
+
+ <EditText
+ android:id="@+id/start_date"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="text" />
+
+ <!-- Wrong, doesn't include e-mail -->
+
+ <EditText
+ android:id="@+id/email_address"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="text" />
+
+ <!-- Wrong, uses wrong password type for PIN -->
+
+ <EditText
+ android:id="@+id/login_pin"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="textPassword" />
+
+ <EditText
+ android:id="@+id/number_of_items"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10" />
+
+ <EditText
+ style="@style/foo"
+ android:id="@+id/number_of_items"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/encoding.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/encoding.xml
new file mode 100644
index 0000000..390aec4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/encoding.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="iso-latin-1"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/encoding2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/encoding2.xml
new file mode 100644
index 0000000..fe6e092
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/encoding2.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="iso-latin-1"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > </LinearLayout> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/fragment.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/fragment.xml
new file mode 100644
index 0000000..bec72b2
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/fragment.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <fragment
+ android:name="android.app.ListFragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <fragment
+ android:name="android.app.DialogFragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:tag="mytag" />
+
+ <fragment
+ android:id="@+id/fragment3"
+ android:name="android.preference.PreferenceFragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/gridlayout.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/gridlayout.xml
new file mode 100644
index 0000000..026f673
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/gridlayout.xml
@@ -0,0 +1,41 @@
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<GridLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:columnCount="2" >
+ <Space
+ android:layout_row="0"
+ android:layout_column="0"
+ android:layout_width="109dip"
+ android:layout_height="108dip"/>
+
+ <Button
+ android:text="Button 1"
+ android:layout_row="0"
+ android:layout_column="1"
+ />
+
+ <Button
+ android:text="Button 2"
+ android:layout_row="1"
+ android:layout_column="3"
+ />
+
+</GridLayout>
+
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/has_children.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/has_children.xml
new file mode 100644
index 0000000..cac27d4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/has_children.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<ListView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ListView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</ListView> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/has_children2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/has_children2.xml
new file mode 100644
index 0000000..bd8c301
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/has_children2.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<ListView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <requestFocus/>
+
+</ListView>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/ignores.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/ignores.xml
new file mode 100644
index 0000000..d4be910
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/ignores.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/newlinear"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <!-- Ignored via attribute, should be hidden -->
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button1"
+ tools:ignore="HardcodedText" >
+ </Button>
+
+ <!-- Inherited ignore from parent -->
+
+ <LinearLayout
+ android:id="@+id/parent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ tools:ignore="HardcodedText" >
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button2" >
+ </Button>
+ </LinearLayout>
+
+ <!-- Hardcoded text warning ignored through "all" -->
+
+ <Button
+ android:id="@+id/button3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button3"
+ tools:ignore="all" >
+ </Button>
+
+ <!-- Ignored through item in ignore list -->
+
+ <Button
+ android:id="@+id/button4"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Hardcoded"
+ tools:ignore="NewApi,HardcodedText" >
+ </Button>
+
+ <!-- Not ignored: should show up as a warning -->
+
+ <Button
+ android:id="@+id/button5"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Hardcoded"
+ tools:ignore="Other" >
+ </Button>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/inefficient_weight.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/inefficient_weight.xml
new file mode 100644
index 0000000..058fde1
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/inefficient_weight.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1.0" />
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+
+ android:orientation="vertical">
+
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1.0" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+
+ android:orientation="vertical">
+
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1.0" />
+
+ </LinearLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/inefficient_weight2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/inefficient_weight2.xml
new file mode 100644
index 0000000..0e7f396
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/inefficient_weight2.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <SeekBar
+ android:id="@+id/seekbar"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:max="100"
+ android:paddingBottom="10dip"
+ android:paddingLeft="15dip"
+ android:paddingRight="15dip"
+ android:paddingTop="10dip"
+ android:secondaryProgress="0"
+ tools:ignore="InefficientWeight" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/labelfor.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/labelfor.xml
new file mode 100644
index 0000000..7d4935c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/labelfor.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/textView1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:labelFor="@+id/editText1"
+ android:text="Medium Text"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <EditText
+ android:id="@+id/editText1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="textPersonName" >
+
+ <requestFocus />
+ </EditText>
+
+ <TextView
+ android:id="@+id/textView2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:labelFor="@+id/autoCompleteTextView1"
+ android:text="TextView" />
+
+ <AutoCompleteTextView
+ android:id="@+id/autoCompleteTextView1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:text="AutoCompleteTextView" />
+
+ <TextView
+ android:id="@+id/textView3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:labelFor="@+id/multiAutoCompleteTextView1"
+ android:text="Large Text"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <MultiAutoCompleteTextView
+ android:id="@+id/multiAutoCompleteTextView1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:text="MultiAutoCompleteTextView" />
+
+ <EditText
+ android:id="@+id/editText2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="textPostalAddress" />
+
+ <AutoCompleteTextView
+ android:id="@+id/autoCompleteTextView2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:text="AutoCompleteTextView" />
+
+ <MultiAutoCompleteTextView
+ android:id="@+id/multiAutoCompleteTextView2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:text="MultiAutoCompleteTextView" />
+
+ <EditText
+ android:id="@+id/editText20"
+ android:hint="Enter your address"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="textPostalAddress" />
+
+
+</LinearLayout> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/labelfor_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/labelfor_ignore.xml
new file mode 100644
index 0000000..41d2821
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/labelfor_ignore.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <EditText
+ android:id="@+id/editText2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="textPostalAddress"
+ tools:ignore="LabelFor"/>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout1.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout1.xml
new file mode 100644
index 0000000..efd6be0
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout1.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <include
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ layout="@layout/layout2" />
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout1_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout1_ignore.xml
new file mode 100644
index 0000000..13bd075
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout1_ignore.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <include
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ layout="@layout/layout2"
+ tools:ignore="DuplicateIncludedIds" />
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout2.xml
new file mode 100644
index 0000000..9fc9c5f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout2.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <RadioButton
+ android:id="@+id/radioButton1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="RadioButton" />
+
+ <include
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ layout="@layout/layout3" />
+
+ <include
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ layout="@layout/layout4" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout3.xml
new file mode 100644
index 0000000..aa5a137
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout3.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <CheckBox
+ android:id="@+id/checkBox1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="CheckBox" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout4.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout4.xml
new file mode 100644
index 0000000..442efd4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/layout4.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/listseparator.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/listseparator.xml
new file mode 100644
index 0000000..ac50ff7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/listseparator.xml
@@ -0,0 +1,3 @@
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@id/text1"
+ style="?android:attr/listSeparatorTextViewStyle" />
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace.xml
new file mode 100644
index 0000000..a984333
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:other="http://foo.bar" android:id="@+id/newlinear" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" orientation="true">
+ <Button style="@style/setupWizardOuterFrame" android.text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
+ <ImageView android:style="@style/bogus" android:id="@+id/android_logo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
+ <LinearLayout other:orientation="horizontal"/>
+</LinearLayout>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace2.xml
new file mode 100644
index 0000000..59001c2
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace2.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:customprefix="http://schemas.android.com/apk/res/android"
+ xmlns:bogus="http://foo.com/bar"
+ customprefix:id="@+id/newlinear"
+ customprefix:layout_width="match_parent"
+ customprefix:layout_height="match_parent"
+ customprefix:orientation="vertical"
+ orientation="true">
+
+ <view class="foo.bar.LinearLayout">
+ bogus:orientation="bogus"
+ </view>
+
+ <foo.bar.LinearLayout
+ customprefix:id="@+id/newlinear2"
+ customprefix:layout_width="match_parent"
+ customprefix:layout_height="match_parent"
+ customprefix:orientation="vertical"
+ bogus:orientation="bogus"
+ orientation="true">
+
+ <view class="foo.bar.LinearLayout">
+ bogus:orientation="bogus"
+ </view>
+
+ </foo.bar.LinearLayout>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace3.xml
new file mode 100644
index 0000000..fcc5aa4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace3.xml
@@ -0,0 +1,17 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res/com.example.apicalltest"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <com.example.library.MyView
+ android:layout_width="300dp"
+ android:layout_height="300dp"
+ android:background="#ccc"
+ android:paddingBottom="40dp"
+ android:paddingLeft="20dp"
+ app:exampleColor="#33b5e5"
+ app:exampleDimension="24sp"
+ app:exampleDrawable="@android:drawable/ic_menu_add"
+ app:exampleString="Hello, MyView" />
+
+</FrameLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace4.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace4.xml
new file mode 100644
index 0000000..e7ecb06
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/namespace4.xml
@@ -0,0 +1,18 @@
+<android.support.v7.widget.GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:app="http://schemas.android.com/apk/res/com.example.apicalltest"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:columnCount="1"
+ tools:context=".MainActivity" >
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:layout_column="0"
+ app:layout_gravity="center"
+ app:layout_row="0"
+ android:text="Button" />
+
+</android.support.v7.widget.GridLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/nested_weights.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/nested_weights.xml
new file mode 100644
index 0000000..a375e06
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/nested_weights.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal" >
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <LinearLayout
+ android:id="@+id/linearLayout1"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <Button
+ android:id="@+id/button3"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Button" />
+ </LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/frameLayout1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" >
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+ </FrameLayout>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/nested_weights2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/nested_weights2.xml
new file mode 100644
index 0000000..7002b89
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/nested_weights2.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" >
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <ImageView
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/launcher_icon" />
+
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="fill_parent"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:text="test" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_weight="1"
+ android:layout_height="0dp"
+ android:orientation="vertical" >
+ </LinearLayout>
+ </LinearLayout>
+
+</FrameLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/note_edit.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/note_edit.xml
new file mode 100644
index 0000000..0b84439
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/note_edit.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <include layout="@layout/colorstrip" android:layout_height="@dimen/colorstrip_height" android:layout_width="match_parent"/>
+
+ <LinearLayout style="@style/TitleBar" android:id="@+id/header">
+ <ImageView style="@style/TitleBarLogo"
+ android:contentDescription="@string/description_logo"
+ android:src="@drawable/title_logo" />
+
+ <View style="@style/TitleBarSpring" />
+
+ <ImageView style="@style/TitleBarSeparator" />
+ <ImageButton style="@style/TitleBarAction"
+ android:id="@+id/btn_title_refresh"
+ android:contentDescription="@string/description_refresh"
+ android:src="@drawable/ic_title_refresh"
+ android:layout_width="wrap_content"
+ android:layout_height="42dp"
+ android:onClick="onRefreshClick" />
+ <ProgressBar style="@style/TitleBarProgressIndicator"
+ android:id="@+id/title_refresh_progress"
+ android:layout_width="wrap_content"
+ android:visibility="visible"/>
+
+ <ImageView style="@style/TitleBarSeparator" />
+ <ImageButton style="@style/TitleBarAction"
+ android:contentDescription="@string/description_search"
+ android:src="@drawable/ic_title_search"
+ android:layout_width="wrap_content"
+ android:layout_height="42dp"
+ android:onClick="onSearchClick" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/noteArea"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_margin="5dip">
+ <EditText
+ android:id="@android:id/text1"
+ android:layout_height="fill_parent"
+ android:hint="@string/note_hint"
+ android:freezesText="true"
+ android:gravity="top" android:layout_width="wrap_content" android:layout_weight="1">
+ </EditText>
+ <EditText
+ android:id="@android:id/text2"
+ android:layout_height="fill_parent"
+ android:freezesText="true"
+ android:gravity="top" android:layout_width="wrap_content" android:layout_weight="1">
+ <requestFocus />
+ </EditText>
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ style="@android:style/ButtonBar">
+ <Button
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:onClick="onSaveClick"
+ android:text="@string/note_save" />
+ <Button
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:onClick="onDiscardClick"
+ android:text="@string/note_discard" />
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/now_playing_after.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/now_playing_after.xml
new file mode 100644
index 0000000..64f681c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/now_playing_after.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/now_playing"
+ android:layout_width="fill_parent"
+ android:layout_height="@dimen/now_playing_height"
+ android:orientation="horizontal">
+ <LinearLayout
+ android:background="@color/background2"
+ android:paddingLeft="14dip"
+ android:paddingRight="14dip"
+ android:paddingTop="10dip"
+ android:paddingBottom="10dip"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/now_playing_title"
+ android:duplicateParentState="true"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textStyle="bold"
+ android:textSize="@dimen/text_size_large"
+ android:textColor="@color/foreground1"
+ android:text="@string/now_playing_after_title"
+ android:maxLines="2"
+ android:ellipsize="end" />
+ <TextView
+ android:id="@+id/now_playing_subtitle"
+ android:duplicateParentState="true"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="3dip"
+ android:textColor="@color/foreground2"
+ android:textSize="@dimen/text_size_small"
+ android:text="@string/now_playing_after_subtitle"
+ android:singleLine="true"
+ android:ellipsize="end" />
+ </LinearLayout>
+ <View
+ android:layout_width="1px"
+ android:layout_height="fill_parent"
+ android:background="@android:color/white" />
+ <ImageButton
+ android:background="@drawable/btn_now_playing_more"
+ android:id="@+id/now_playing_more"
+ android:src="@drawable/ic_now_playing_logo"
+ android:padding="12dip"
+ android:layout_width="100mm"
+ android:layout_height="120in"
+ android:onClick="onNowPlayingLogoClick"
+ android:scaleType="center" />
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/onclick.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/onclick.xml
new file mode 100644
index 0000000..882c035
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/onclick.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="nonexistent"
+ android:text="Button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="wrong1"
+ android:text="Button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="wrong2"
+ android:text="Button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="wrong3"
+ android:text="Button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="wrong4"
+ android:text="Button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="wrong5"
+ android:text="Button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="wrong6"
+ android:text="Button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="ok"
+ android:text="Button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="simple_typo"
+ android:text="Button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="my\u1234method"
+ android:text="Button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="wrong7"
+ android:text="Button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="@string/ok"
+ android:text="Button" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/private.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/private.xml
new file mode 100644
index 0000000..c98797d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/private.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/newlinear" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
+ <ImageView android:id="@+id/android_logo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@*android:drawable/android_button" android:focusable="false" android:clickable="false" />
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/scrolling.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/scrolling.xml
new file mode 100644
index 0000000..0bed702
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/scrolling.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ListView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/simple.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/simple.xml
new file mode 100644
index 0000000..d462c69
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/simple.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/simple_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/simple_ignore.xml
new file mode 100644
index 0000000..1b3de90
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/simple_ignore.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:ignore="MergeRootFrame" />
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/simpleinclude.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/simpleinclude.xml
new file mode 100644
index 0000000..4cb994b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/simpleinclude.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <include
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ layout="@layout/simple" />
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/size.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/size.xml
new file mode 100644
index 0000000..e4d4a9b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/size.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <RadioButton
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <RadioButton
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:text="Button" />
+
+ <EditText
+ android:id="@+id/edittext"
+ android:layout_height="wrap_content"
+ android:text="EditText" />
+
+ <EditText
+ android:id="@+id/edittext2"
+ android:text="EditText" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/size2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/size2.xml
new file mode 100644
index 0000000..d06d00f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/size2.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ tools:ignore="HardcodedText" >
+
+ <Button
+ android:id="@+id/button1"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ style="@style/WidthAndHeight"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button3"
+ style="@style/Width"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button4"
+ style="@style/MyStyle"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button5"
+ style="@style/MyStyle.Big"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button6"
+ style="@style/MyOtherStyle"
+ android:text="Button" />
+
+ <include
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ layout="@layout/sizeincluded" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/sizeincluded.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/sizeincluded.xml
new file mode 100644
index 0000000..5fccff6
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/sizeincluded.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical" >
+
+</LinearLayout> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/textsize.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/textsize.xml
new file mode 100644
index 0000000..610867e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/textsize.xml
@@ -0,0 +1,51 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/LinearLayout1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="14dp" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="14dip" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="14sp" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="@android/dimen/mysizedp" />
+
+ <!-- Small -->
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="11sp" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="6sp" />
+
+ <!-- No warnings: wrong attribute, size == 0, etc -->
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="0sp" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:marginTop="5sp" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/too_deep.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/too_deep.xml
new file mode 100644
index 0000000..7e92008
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/too_deep.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/too_many.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/too_many.xml
new file mode 100644
index 0000000..e2dbd6b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/too_many.xml
@@ -0,0 +1,413 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ok" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+</FrameLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/unused_namespace.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/unused_namespace.xml
new file mode 100644
index 0000000..f633e4b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/unused_namespace.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<foo.bar.LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:unused1="http://schemas.android.com/apk/res/unused1"
+ xmlns:unused2="http://schemas.android.com/apk/res/unused1"
+ xmlns:unused3="http://foo.bar.com/foo"
+ xmlns:notunused="http://schemas.android.com/apk/res/notunused"
+ xmlns:tools="http://schemas.android.com/tools" >
+
+ <foo.bar.Button
+ notunused:foo="Foo"
+ tools:ignore="HardcodedText" >
+ </foo.bar.Button>
+
+</foo.bar.LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/useless.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/useless.xml
new file mode 100644
index 0000000..c317235
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/useless.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <!-- Neither parent nor child define background: delete is okay -->
+
+ <FrameLayout
+ android:id="@+id/LinearLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+ </FrameLayout>
+
+ <!-- Both define background: cannot be deleted -->
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/bg" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/bg" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+ </FrameLayout>
+
+ <!-- Only child defines background: delete is okay -->
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/bg" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+ </FrameLayout>
+
+ <!-- Only parent defines background: delete is okay -->
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/bg" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+ </FrameLayout>
+
+ <!-- Leaf cannot be deleted because it has a background -->
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/bg" >
+ </FrameLayout>
+
+ <!-- Useless leaf -->
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ </FrameLayout>
+</merge>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/useless2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/useless2.xml
new file mode 100644
index 0000000..a819036
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/useless2.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <TabWidget
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </FrameLayout>
+ </LinearLayout>
+
+</TabHost>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/useless3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/useless3.xml
new file mode 100644
index 0000000..1d9e9b7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/useless3.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TableRow
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/keyboard_table_row">
+</TableRow>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong0dp.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong0dp.xml
new file mode 100644
index 0000000..136329f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong0dp.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ tools:ignore="HardcodedText" >
+
+ <!-- Vertical Layout -->
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <!-- No weight: Always an error -->
+
+ <Button
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:text="Button" />
+
+ <!--
+ 0dp not along the orientation axis is wrong;
+ here layout_height is okay, layout_width is not
+ -->
+
+ <Button
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1.0"
+ android:text="Button" />
+
+ <!-- OK -->
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:layout_weight="1.0"
+ android:text="Button" />
+ </LinearLayout>
+
+ <!-- Horizontal Layout -->
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal" >
+
+ <!-- OK -->
+
+ <Button
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1.0"
+ android:text="Button" />
+
+ <!-- Not OK -->
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:layout_weight="1.0"
+ android:text="Button" />
+ </LinearLayout>
+
+ <!-- No orientation specified, so horizontal -->
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <!-- OK -->
+
+ <Button
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1.0"
+ android:text="Button" />
+
+ <!-- Not OK -->
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:layout_weight="1.0"
+ android:text="Button" />
+
+ <!-- Check suppressed -->
+
+ <Button
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="Button"
+ tools:ignore="Suspicious0dp" />
+ </LinearLayout>
+
+</FrameLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_dimension.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_dimension.xml
new file mode 100644
index 0000000..79b922b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_dimension.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<HorizontalScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</HorizontalScrollView>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace.xml
new file mode 100644
index 0000000..c6e2143
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/andriod"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <include
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ layout="@layout/layout2" />
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace2.xml
new file mode 100644
index 0000000..49dc611
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace2.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/Android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <include
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ layout="@layout/layout2" />
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace3.xml
new file mode 100644
index 0000000..02252b4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace3.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:a="http://schemas.android.com/apk/res/androi"
+ a:layout_width="match_parent"
+ a:layout_height="match_parent"
+ a:orientation="vertical" >
+
+ <include
+ a:layout_width="wrap_content"
+ a:layout_height="wrap_content"
+ layout="@layout/layout2" />
+
+ <Button
+ a:id="@+id/button1"
+ a:layout_width="wrap_content"
+ a:layout_height="wrap_content"
+ a:text="Button" />
+
+ <Button
+ a:id="@+id/button2"
+ a:layout_width="wrap_content"
+ a:layout_height="wrap_content"
+ a:text="Button" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace4.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace4.xml
new file mode 100644
index 0000000..4142622
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace4.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This file does *not* have a wrong namespace: it's testdata to make sure we don't complain when "a" is defined for something unrelated -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:a="http://something/very/different"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <include
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ layout="@layout/layout2" />
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace5.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace5.xml
new file mode 100644
index 0000000..ce0fc4b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrong_namespace5.xml
@@ -0,0 +1,10 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:noturi="tp://schems.android.com/apk/res/com.my.package"
+ xmlns:typo1="http://schems.android.com/apk/res/com.my.package"
+ xmlns:typo2="http://schems.android.comm/apk/res/com.my.package"
+ xmlns:ok="http://foo.bar/res/unrelated"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+</RelativeLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams.xml
new file mode 100644
index 0000000..9c8bd5c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Button" />
+
+ <LinearLayout
+ android:id="@+id/relativeLayout1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginLeft="17dp"
+ android:layout_marginTop="16dp"
+ android:text="Button" />
+
+ <TextView
+ android:id="@+id/textView1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@+id/button1"
+ android:layout_toRightOf="@+id/button1"
+ android:text="Medium Text"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <RadioButton
+ android:id="@+id/radioButton1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@+id/button1"
+ android:layout_below="@+id/button1"
+ android:text="RadioButton" />
+ </LinearLayout>
+ <TableLayout
+ android:id="@+id/tableLayout1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <TableRow
+ android:id="@+id/tableRow1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:id="@+id/button3"
+ android:layout_column="0"
+ android:layout_span="1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Button" />
+ </TableRow>
+
+ <Button
+ android:id="@+id/button4"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Button" />
+ </TableLayout>
+
+ <GridLayout
+ android:id="@+id/gridLayout1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <Button
+ android:id="@+id/button10"
+ android:layout_column="0"
+ android:layout_row="0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </GridLayout>
+
+</FrameLayout>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams2.xml
new file mode 100644
index 0000000..309dffd
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams2.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <foo.bar.ActionBarHost
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <FrameLayout
+ android:layout_width="fill_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+ </foo.bar.ActionBarHost>
+
+</merge>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams3.xml
new file mode 100644
index 0000000..79173c7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams3.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentTop="true" >
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams4.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams4.xml
new file mode 100644
index 0000000..802e215
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams4.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <include
+ android:id="@+id/include1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ layout="@layout/wrongparams3" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams5.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams5.xml
new file mode 100644
index 0000000..947bf48
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams5.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:text="Button" />
+
+</merge>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams6.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams6.xml
new file mode 100644
index 0000000..8691d7c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams6.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <include
+ android:id="@+id/include1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ layout="@layout/wrongparams5" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams_ignore.xml
new file mode 100644
index 0000000..d0e6ff0
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/layout/wrongparams_ignore.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Button" />
+
+ <LinearLayout
+ android:id="@+id/relativeLayout1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginLeft="17dp"
+ android:layout_marginTop="16dp"
+ android:text="Button"
+ tools:ignore="all" />
+
+ <TextView
+ android:id="@+id/textView1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@+id/button1"
+ android:layout_toRightOf="@+id/button1"
+ android:text="Medium Text"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ tools:ignore="ObsoleteLayoutParam" />
+
+ <RadioButton
+ android:id="@+id/radioButton1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@+id/button1"
+ android:layout_below="@+id/button1"
+ android:text="RadioButton"
+ tools:ignore="ObsoleteLayoutParam" />
+ </LinearLayout>
+ <TableLayout
+ android:id="@+id/tableLayout1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <TableRow
+ android:id="@+id/tableRow1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:id="@+id/button3"
+ android:layout_column="0"
+ android:layout_span="1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Button" />
+ </TableRow>
+
+ <Button
+ android:id="@+id/button4"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Button" />
+ </TableLayout>
+
+ <GridLayout
+ android:id="@+id/gridLayout1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <Button
+ android:id="@+id/button10"
+ android:layout_column="0"
+ android:layout_row="0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </GridLayout>
+
+</FrameLayout>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu-land/actions.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu-land/actions.xml
new file mode 100644
index 0000000..89fa751
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu-land/actions.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/menu_search"
+ android:showAsAction="always|collapseActionView"
+ android:actionViewClass="android.widget.SearchView" />
+
+ <group android:id="@+id/reader_items">
+
+ <item
+ android:id="@+id/menu_table_of_contents"
+ android:showAsAction="always"
+ android:actionLayout="@layout/action_table_of_contents" />
+
+ <item
+ android:id="@+id/menu_settings"
+ android:showAsAction="always" />
+
+ <item android:id="@+id/menu_mode"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_buy"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_about"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_share"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_keep"
+ android:checkable="true"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_d"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_help"
+ android:showAsAction="never" />
+
+ </group>
+
+ <group android:id="@+id/search_items">
+
+ <item
+ android:id="@+id/menu_table_of_contents"
+ android:showAsAction="always"
+ android:actionLayout="@layout/action_table_of_contents" />
+
+ <item android:id="@+id/menu_search_exit"
+ android:showAsAction="never" />
+
+ </group>
+
+</menu>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu-land/actions2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu-land/actions2.xml
new file mode 100644
index 0000000..35b85d4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu-land/actions2.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/menu_search"
+ android:showAsAction="always|collapseActionView"
+ android:actionViewClass="android.widget.SearchView" />
+
+ <group android:id="@+id/reader_items">
+
+ <item
+ android:id="@+id/menu_table_of_contents"
+ android:showAsAction="always|collapseActionView"
+ android:actionLayout="@layout/action_table_of_contents" />
+
+ <item
+ android:id="@+id/menu_settings"
+ android:showAsAction="always|collapseActionView" />
+
+ <item android:id="@+id/menu_mode"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_buy"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_about"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_share"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_keep"
+ android:checkable="true"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_d"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_help"
+ android:showAsAction="never" />
+
+ </group>
+
+ <group android:id="@+id/search_items">
+
+ <item
+ android:id="@+id/menu_table_of_contents"
+ android:showAsAction="always|collapseActionView"
+ android:actionLayout="@layout/action_table_of_contents" />
+
+ <item android:id="@+id/menu_search_exit"
+ android:showAsAction="never" />
+
+ </group>
+
+</menu>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu-land/actions2_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu-land/actions2_ignore.xml
new file mode 100644
index 0000000..47cd32e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu-land/actions2_ignore.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools">
+
+ <item
+ android:id="@+id/menu_search"
+ android:showAsAction="always|collapseActionView"
+ android:actionViewClass="android.widget.SearchView"
+ tools:ignore="AlwaysShowAction" />
+
+ <group android:id="@+id/reader_items">
+
+ <item
+ android:id="@+id/menu_table_of_contents"
+ android:showAsAction="always|collapseActionView"
+ android:actionLayout="@layout/action_table_of_contents" />
+
+ <item
+ android:id="@+id/menu_settings"
+ android:showAsAction="always|collapseActionView" />
+
+ <item android:id="@+id/menu_mode"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_buy"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_about"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_share"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_keep"
+ android:checkable="true"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_d"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_help"
+ android:showAsAction="never" />
+
+ </group>
+
+ <group android:id="@+id/search_items">
+
+ <item
+ android:id="@+id/menu_table_of_contents"
+ android:showAsAction="always|collapseActionView"
+ android:actionLayout="@layout/action_table_of_contents" />
+
+ <item android:id="@+id/menu_search_exit"
+ android:showAsAction="never" />
+
+ </group>
+
+</menu>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu/menu.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu/menu.xml
new file mode 100644
index 0000000..4f0839b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu/menu.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/item1"
+ android:icon="@drawable/icon1"
+ android:title="My title 1">
+ </item>
+ <item
+ android:id="@+id/item2"
+ android:icon="@drawable/icon2"
+ android:showAsAction="ifRoom"
+ android:title="My title 2">
+ </item>
+
+</menu> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu/titles.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu/titles.xml
new file mode 100644
index 0000000..a1ae5bb
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/menu/titles.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/action_bar_progress_spinner"
+ android:showAsAction="always"
+ android:background="@null"
+ android:selectableItemBackground="@null"
+ android:actionLayout="@layout/action_bar_progress_spinner_layout"/>
+ <item android:id="@+id/refresh"
+ android:title="@string/menu_refresh"
+ android:showAsAction="always"
+ android:icon="@drawable/ic_menu_refresh"/>
+ <item android:id="@+id/menu_plus_one"
+ android:showAsAction="always"
+ android:icon="@drawable/ic_menu_plus1"/>
+</menu>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/private_key.pem b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/private_key.pem
new file mode 100644
index 0000000..03b9477
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/private_key.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,77F426A58B274623
+
+FH1NdgJgrX1OGKM0WfzwWUWmLTmfawdaUPeFNJbz1+WJ5DEt1DmC6o0QkXoxIPC
+Te/+FS80gNruYgYIWu4WXWtCSdvSfGI8LP1JZ7hmMCW055J2mLVKT4o6HqAQnHrb
+hTATVG6CB/GdHTFPG3J65qIyTlG50jyzfwZtliMCCAWi+AaAlo5xzUe0DgedytB2
+sFkLq5EiD6066P/LXPH/Z5WJKiMCFOl0Gjwd3M9ohZufnWJPJT5ap2fm7OSJSfa6
+jPREY+UwhPyKkYOc2cWgojj6HrsSQlXPl176b1+31c19hhhRAtDfJBIU2OrOFVk/
+V88/Dm0I+ROyLme0rYfFg8uHz2aIymWEMds5ZKEFTFbBhaWbVYKIX7+82tftnd+P
+2kT15JAK9V27F0p4SRiWQ5RsDkT3rBWWjtk9Rptkrgec9WKoTaO2fT8bPaWFR/M1
+6X7kjMqhLw1sHmsSeDKx0YCWfS+gWh7RPWGQ2EfH2pxoZkWAR5R3cZCEn3Ia1BeV
+UTFWy+DwjEeSrNkO96E0WH1r8204cJAKK8cWS4HSAPMsQPf5cZjIrrAak/9Wupkq
+fnrB0Ae6GFO2gWHYQfbSWdEq6w5+S6XZyTauVyaJAjjIFWmegfaKWHzNvqCWJ4T
+YPsiptUrKz6WWYyhiUrNJQKcyGWHWrwMNIblWqSBNCa8OIVoaZiRibgO1SIafAGAS
+9MDXXVaY6rqx1yfZYDcWVgKGXTJhBXALCeGMWF43bvAmPq3M13QJA0rlO7lAUUF2
+5INqBUeJxZWYxn6tRr9WMty/UcYnPR3YHgt0RDZycvbcqPsU5tHk9Q==
+-----END RSA PRIVATE KEY----- \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-cs/arrays.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-cs/arrays.xml
new file mode 100644
index 0000000..dd8e580
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-cs/arrays.xml
@@ -0,0 +1,9 @@
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="security_questions">
+ <item>"Oblíbené jídlo?"</item>
+ <item>"Město narození."</item>
+ <item>"Jméno nejlepšího kamaráda z dětství?"</item>
+ <item>"Název střední školy"</item>
+ </string-array>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-cs/strings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-cs/strings.xml
new file mode 100644
index 0000000..2830534
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-cs/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="home_title">"Domů"</string>
+ <string name="show_all_apps">"Vše"</string>
+ <string name="menu_wallpaper">"Tapeta"</string>
+ <string name="menu_search">"Hledat"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Klepnutím na obrázek nastavíte tapetu portrétu"</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-cs/translatedarrays.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-cs/translatedarrays.xml
new file mode 100644
index 0000000..f20dd3a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-cs/translatedarrays.xml
@@ -0,0 +1,4 @@
+<resources>
+ <string name="item1">Item1-cs</string>
+ <string name="item2">Item2-cs</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-de-rDE/strings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-de-rDE/strings.xml
new file mode 100644
index 0000000..82510ae
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-de-rDE/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="home_title">"Startseite"</string>
+ <string name="show_all_apps">"Alle"</string>
+ <string name="menu_wallpaper">"Bildschirmhintergrund"</string>
+ <string name="menu_search">"Suchen"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Tippen Sie auf Bild, um Porträt-Bildschirmhintergrund einzustellen"</string>
+ <string name="continue_skip_label">"Weiter"</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-de/strings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-de/strings.xml
new file mode 100644
index 0000000..055dd52
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-de/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">Unit Test</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-de/typos.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-de/typos.xml
new file mode 100644
index 0000000..5108cc9
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-de/typos.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="s1">
+
+ wo befindet eine ip
+
+ </string>
+ <string name="s2">(Authorisierungscode!)</string>
+ <string name="s3"> zurück gefoobaren!</string>
+ <!-- escaped separator -->
+ <string name="issue39599">"ü test\nciht zu"</string>
+
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es-rUS/strings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..4de53dd
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es-rUS/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="menu_search">"Búsqueda"</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/donottranslate.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/donottranslate.xml
new file mode 100644
index 0000000..f28594c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/donottranslate.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="full_wday_month_day_no_year">EEEE, d MMMM</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/formatstrings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/formatstrings.xml
new file mode 100644
index 0000000..4ef3d94
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/formatstrings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hello">%1$d</string>
+ <string name="hello2">%3$d: %1$s, %2$s?</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/formatstrings_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/formatstrings_ignore.xml
new file mode 100644
index 0000000..0cf7008
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/formatstrings_ignore.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <string name="hello" tools:ignore="StringFormatMatches">%1$d</string>
+ <string name="hello2" tools:ignore="StringFormatMatches,StringFormatCount">%3$d: %1$s, %2$s?</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/strings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/strings.xml
new file mode 100644
index 0000000..ae5822a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="home_title">"Casa"</string>
+ <string name="show_all_apps">"Todo"</string>
+ <string name="menu_wallpaper">"Papel tapiz"</string>
+ <string name="menu_search">"Búsqueda"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Puntee en la imagen para establecer papel tapiz vertical"</string>
+
+ <string-array name="security_questions">
+ <item>"Comida favorita"</item>
+ <item>"Ciudad de nacimiento"</item>
+ <item>"Nombre de tu mejor amigo/a de la infancia"</item>
+ <item>"Nombre de tu colegio"</item>
+ </string-array>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/strings_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/strings_ignore.xml
new file mode 100644
index 0000000..4358448
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/strings_ignore.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="home_title">"Casa"</string>
+ <string name="show_all_apps">"Todo"</string>
+ <string name="menu_wallpaper">"Papel tapiz"</string>
+ <string name="menu_search">"Búsqueda"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Puntee en la imagen para establecer papel tapiz vertical"</string>
+ <string name="other" tools:ignore="ExtraTranslation">"?"</string>
+
+ <string-array name="security_questions" tools:ignore="ExtraTranslation">
+ <item>"Comida favorita"</item>
+ <item>"Ciudad de nacimiento"</item>
+ <item>"Nombre de tu mejor amigo/a de la infancia"</item>
+ <item>"Nombre de tu colegio"</item>
+ </string-array>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/strings_locale.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/strings_locale.xml
new file mode 100644
index 0000000..b485dee
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-es/strings_locale.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:locale="es">
+ <string name="home_title">"Casa"</string>
+ <string name="show_all_apps">"Todo"</string>
+ <string name="menu_wallpaper">"Papel tapiz"</string>
+ <string name="menu_search">"Búsqueda"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Puntee en la imagen para establecer papel tapiz vertical"</string>
+
+ <string-array name="security_questions">
+ <item>"Comida favorita"</item>
+ <item>"Ciudad de nacimiento"</item>
+ <item>"Nombre de tu mejor amigo/a de la infancia"</item>
+ <item>"Nombre de tu colegio"</item>
+ </string-array>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-fr/strings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-fr/strings.xml
new file mode 100644
index 0000000..85a28c9
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-fr/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string-array name="test_string_array">
+ <item>Test (French)</item>
+ </string-array>
+
+</resources> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-it/stringarrays.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-it/stringarrays.xml
new file mode 100644
index 0000000..7bd83e9
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-it/stringarrays.xml
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='utf-8'?>
+<resources>
+ <string-array name="track_type_desc">
+ <item>Pendenza</item>
+ </string-array>
+ <string-array name="map_density_desc">
+ <item>Automatico (mappa leggibile su display HD)</item>
+ </string-array>
+ <string-array name="cache_size_desc">
+ <item>Piccolo (100)</item>
+ </string-array>
+</resources> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-land/arrays.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-land/arrays.xml
new file mode 100644
index 0000000..4495dfd
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-land/arrays.xml
@@ -0,0 +1,11 @@
+<resources>
+ <array name="signal_strength">
+ <item>@drawable/ic_setups_signal_0</item>
+ <item>@drawable/ic_setups_signal_1</item>
+ <item>@drawable/ic_setups_signal_2</item>
+ <item>@drawable/ic_setups_signal_3</item>
+ <item>@drawable/ic_setups_signal_4</item>
+ <item>@drawable/extra</item>
+ </array>
+</resources>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-land/arrays_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-land/arrays_ignore.xml
new file mode 100644
index 0000000..24e76cd
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-land/arrays_ignore.xml
@@ -0,0 +1,11 @@
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <array name="signal_strength" tools:ignore="InconsistentArrays">
+ <item>@drawable/ic_setups_signal_0</item>
+ <item>@drawable/ic_setups_signal_1</item>
+ <item>@drawable/ic_setups_signal_2</item>
+ <item>@drawable/ic_setups_signal_3</item>
+ <item>@drawable/ic_setups_signal_4</item>
+ <item>@drawable/extra</item>
+ </array>
+</resources>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-land/strings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-land/strings.xml
new file mode 100644
index 0000000..824df2a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-land/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <!-- Wallpaper -->
+ <string name="wallpaper_instructions">Tap image to set landscape wallpaper</string>
+</resources>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nb/typos.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nb/typos.xml
new file mode 100644
index 0000000..06cec0d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nb/typos.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- No typos -->
+ <string name="s1">Dette er en test</string>
+ <!-- Plain typos -->
+ <string name="s2">Mer morro med Andriod</string>
+ <!-- Make capitalization match typo -->
+ <string name="s3"> Parallel </string>
+ <!-- Markup indirection -->
+ <string name="s4"><b>altid</b></string>
+ <!-- Typo, match capitalized -->
+ <string name="s5">Altid</string>
+ <!-- random words, shouldn't flag -->
+ <string name="s6">abcdefg qwerty asdf jklm</string>
+ <!-- typo, but should only match when capitalized -->
+ <string name="s7">Midt-Østen midt-østen</string>
+ <!-- Non-ASCII UTF-8 string -->
+ <string name="s7">Koding er en spennende karriære</string>
+ <string name="internet">"Koble til Internett.</string>
+
+</resources>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nb/typos_locale.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nb/typos_locale.xml
new file mode 100644
index 0000000..ed1edd1
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nb/typos_locale.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools"
+ tools:locale="nb">
+ <!-- Markup indirection -->
+ <string name="s4"><b>altid</b></string>
+ <!-- Typo, match capitalized -->
+ <string name="s5">Altid</string>
+</resources> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nl-rNL/arrays.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nl-rNL/arrays.xml
new file mode 100644
index 0000000..36faf96
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nl-rNL/arrays.xml
@@ -0,0 +1,8 @@
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="security_questions">
+ <item>"Favoriete eten?"</item>
+ <item>"Geboorteplaats?"</item>
+ <item>"Naam van middelbare school?"</item>
+ </string-array>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nl-rNL/strings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nl-rNL/strings.xml
new file mode 100644
index 0000000..1bd9ea2
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values-nl-rNL/strings.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="home_title">"Start"</string>
+ <!-- Commented out in the unit test to generate extra warnings:
+ <string name="show_all_apps">"Alles"</string>
+ <string name="menu_wallpaper">"Achtergrond"</string>
+ -->
+ <string name="menu_search">"Zoeken"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Tik op afbeelding om portretachtergrond in te stellen"</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/arrays.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/arrays.xml
new file mode 100644
index 0000000..de544b3
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/arrays.xml
@@ -0,0 +1,18 @@
+<resources>
+ <!-- Choices for Locations in SetupWizard's Set Time and Data Activity -->
+ <string-array name="security_questions">
+ <item>Favorite food?</item>
+ <item>City of birth?</item>
+ <item>Best childhood friend\'s name?</item>
+ <item>Highschool name?</item>
+ </string-array>
+
+ <array name="signal_strength">
+ <item>@drawable/ic_setups_signal_0</item>
+ <item>@drawable/ic_setups_signal_1</item>
+ <item>@drawable/ic_setups_signal_2</item>
+ <item>@drawable/ic_setups_signal_3</item>
+ <item>@drawable/ic_setups_signal_4</item>
+ </array>
+</resources>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/arrayusage.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/arrayusage.xml
new file mode 100644
index 0000000..0b890f7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/arrayusage.xml
@@ -0,0 +1,6 @@
+<resources>
+<string name="my_item">An Item</string>
+<string-array name="my_array">
+ <item>@string/my_item</item>
+</string-array>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/buttonbar-values.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/buttonbar-values.xml
new file mode 100644
index 0000000..4a32e7d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/buttonbar-values.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="button"> Button </string>
+ <string name="ok"> OK </string>
+ <string name="cancel"> Cancel </string>
+ <string name="resume"> OK </string>
+ <string name="giveup"> Cancel </string>
+ <string name="resume2"> Ok </string>
+ <string name="giveup2">"CANCEL"</string>
+ <string name="send"> Send </string>
+ <string name="abort">Abort</string>
+ <string name="goback">'Back'</string>
+
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/customattr.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/customattr.xml
new file mode 100644
index 0000000..e1ca2d4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/customattr.xml
@@ -0,0 +1,6 @@
+<resources>
+ <declare-styleable name="ContentFrame">
+ <attr name="content" format="reference" />
+ <attr name="contentId" format="reference" />
+ </declare-styleable>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings-version1.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings-version1.xml
new file mode 100644
index 0000000..4d3e5a7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings-version1.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hour_minute_24">%-k:%M</string>
+ <string name="numeric_date">%Y-%m-%d</string>
+ <string name="month_day_year">%Y %B %-e</string>
+ <string translatable="false" name="web_user_agent">
+ Foo (Bar %s) Foo/731.11+ (Foo, like Bar) Version/1.2.3 Foo Bar/123.14.4
+ </string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings-version2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings-version2.xml
new file mode 100644
index 0000000..d1757f7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings-version2.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hour_minute_24">%H:%M</string>
+ <string name="numeric_date">%-m/%-e/%Y</string>
+ <string name="month_day_year">%B %-e, %Y</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings.xml
new file mode 100644
index 0000000..6b1985c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hello">Hello %1$s</string>
+ <string name="hello2">Hello %1$s, %2$s?</string>
+ <string name="missing">Hello %3$s World</string>
+ <string name="score">Score: %1$d</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings2.xml
new file mode 100644
index 0000000..23291d2
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings2.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hour_minute_24">%H:%M</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string>
+ <string name="bogus">%2.99999s</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings3.xml
new file mode 100644
index 0000000..2424078
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings3.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="multiple_formats_with_percentage">%1$s 3%% %2$s</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings4.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings4.xml
new file mode 100644
index 0000000..c4e245e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings4.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="formattest1">"%1$s, %2$tF %3$tR"</string>
+ <string name="formattest2">%1$s, %2$tF %3$tR</string>
+ <string name="formattest3">"Note: Start point RPM differs by %d%%.\n\n"</string>
+ <string name="formattest4">Note: Start point RPM differs by %d%%.\n\n</string>
+ <string name="formattest5">%s%% c</string>
+ <string name="formattest6">%s%% </string>
+ <string name="formattest7">%1$s%%</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings_ignore.xml
new file mode 100644
index 0000000..9834119
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/formatstrings_ignore.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <string name="hello" tools:ignore="StringFormatMatches">Hello %1$s</string>
+ <string name="hello2" tools:ignore="StringFormatMatches,StringFormatCount">Hello %1$s, %2$s?</string>
+ <string name="missing" tools:ignore="StringFormatCount">Hello %3$s World</string>
+ <string name="score">Score: %1$d</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/nontranslatable.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/nontranslatable.xml
new file mode 100644
index 0000000..f608bff
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/nontranslatable.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="dummy" translatable="false">Ignore Me</string>
+</resources>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/nontranslatable2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/nontranslatable2.xml
new file mode 100644
index 0000000..4fcfdc6
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/nontranslatable2.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="dummy">Ignore Me</string>
+</resources>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/plurals.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/plurals.xml
new file mode 100644
index 0000000..703a841
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/plurals.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <plurals name="my_plural">
+ <item quantity="one">@string/hello</item>
+ <item quantity="few">@string/hello</item>
+ <item quantity="other">@string/hello</item>
+ </plurals>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/pxsp.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/pxsp.xml
new file mode 100644
index 0000000..7a44201
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/pxsp.xml
@@ -0,0 +1,34 @@
+<resources>
+ <style name="Style1">
+ <item name="android:textSize">50sp</item>
+ </style>
+ <style name="Style2">
+ <item name="android:textSize">50dp</item>
+ </style>
+ <style name="Style3">
+ <item name="android:textSize">50px</item>
+ </style>
+ <style name="Style4">
+ <item name="android:textSize"> 50dip </item>
+ </style>
+
+ <style name="Style5">
+ <item name="android:paddingLeft">@dimen/whats_on_item_padding</item>
+ <item name="android:paddingRight"> 50px </item>
+ <item name="android:paddingTop">50px</item>
+ <item name="android:paddingBottom">50dip</item>
+ </style>
+
+ <style name="Style6">
+ <item name="android:textSize">50mm</item>
+ <item name="android:textSize">
+ 50in
+ </item>
+ </style>
+
+ <style name="Widget.TabStrip" parent="Widget">
+ <item name="android:divider">?android:attr/listDivider</item>
+ <item name="android:showDividers">middle</item>
+ <item name="android:dividerPadding">0px</item>
+ </style>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/sizestyles.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/sizestyles.xml
new file mode 100644
index 0000000..468974e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/sizestyles.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <style name="WidthAndHeight" parent="@android:attr/textAppearanceMedium">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">match_parent</item>
+ </style>
+
+ <style name="Width" parent="@android:attr/textAppearanceMedium">
+ <item name="android:layout_width">match_parent</item>
+ </style>
+
+ <style name="MyStyle" parent="@style/WidthAndHeight"></style>
+ <style name="MyStyle.Big"></style>
+ <style name="MyOtherStyle" parent="@style/MyStyle.Big"></style>
+
+</resources> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/stringarrays.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/stringarrays.xml
new file mode 100644
index 0000000..6405580
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/stringarrays.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string-array name="map_density_desc">
+ <item>Automatic (readable map on HD displays)</item>
+ <item>1 map pixel = 1 screen pixel</item>
+ <item>1 map pixel = 1.25 screen pixels</item>
+ <item>1 map pixel = 1.5 screen pixels</item>
+ <item>1 map pixel = 2 screen pixels</item>
+ </string-array>
+ <string-array name="spatial_resolution_desc">
+ <item>5m/yd (fine, default)</item>
+ </string-array>
+</resources> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings.xml
new file mode 100644
index 0000000..5aec951
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <!-- Home -->
+ <string name="home_title">Home Sample</string>
+ <string name="show_all_apps">All</string>
+
+ <!-- Home Menus -->
+ <string name="menu_wallpaper">Wallpaper</string>
+ <string name="menu_search">Search</string>
+ <string name="menu_settings">Settings</string>
+ <string name="dummy" translatable="false">Ignore Me</string>
+
+ <!-- Wallpaper -->
+ <string name="wallpaper_instructions">Tap picture to set portrait wallpaper</string>
+</resources>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings2.xml
new file mode 100644
index 0000000..bce9e32
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings2.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hello">Hello</string>
+</resources>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings3.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings3.xml
new file mode 100644
index 0000000..6da33ae
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings3.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
+
+ <string name="test_string">Test (English)</string>
+
+ <string-array name="test_string_array">
+ <item>@string/test_string</item>
+ </string-array>
+
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings4.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings4.xml
new file mode 100644
index 0000000..76d88a4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings4.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <string name="hello">Hello</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings_ignore.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings_ignore.xml
new file mode 100644
index 0000000..a69d4c8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/strings_ignore.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <!-- Home -->
+ <string name="home_title">Home Sample</string>
+ <string name="show_all_apps" tools:ignore="MissingTranslation">All</string>
+
+ <!-- Home Menus -->
+ <string name="menu_wallpaper" tools:ignore="MissingTranslation">Wallpaper</string>
+ <string name="menu_search">Search</string>
+ <string name="menu_settings" tools:ignore="all">Settings</string>
+ <string name="dummy" translatable="false">Ignore Me</string>
+
+ <!-- Wallpaper -->
+ <string name="wallpaper_instructions">Tap picture to set portrait wallpaper</string>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/stylecycle.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/stylecycle.xml
new file mode 100644
index 0000000..448eb9c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/stylecycle.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <style name="PropertyToggle" parent="@style/PropertyToggle.Base"></style>
+ <style name="PropertyToggle.Base"></style>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/styles.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/styles.xml
new file mode 100644
index 0000000..34e2d6f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/styles.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+<style name="DetailsPage_BuyButton" parent="@style/DetailsPage_Button">
+ <item name="android:textColor">@color/buy_button</item>
+ <item name="android:background">@drawable/details_page_buy_button</item>
+</style>
+
+<style name="DetailsPage_EditorialBuyButton" parent="@style/DetailsPage_EditorialBuyButton" />
+<!-- Should have been:
+<style name="DetailsPage_EditorialBuyButton" parent="@style/DetailsPage_BuyButton" />
+-->
+
+</resources>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/themes.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/themes.xml
new file mode 100644
index 0000000..eba1c3c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/themes.xml
@@ -0,0 +1,8 @@
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <style name="MyTheme" parent="@android:style/Theme">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ </style>
+
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/themes2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/themes2.xml
new file mode 100644
index 0000000..b587923
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/themes2.xml
@@ -0,0 +1,10 @@
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <style name="MyStyle" parent="@style/Theme.Holo.Light"></style>
+ <style name="MyStyle.Big"></style>
+ <style name="MyOtherStyle" parent="@style/MyStyle.Big">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ </style>
+
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/translatedarrays.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/translatedarrays.xml
new file mode 100644
index 0000000..4707734
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/translatedarrays.xml
@@ -0,0 +1,8 @@
+<resources>
+ <string name="item1">Item1</string>
+ <string name="item2">Item2</string>
+ <string-array name="myarray">
+ <item>@string/item1</item>
+ <item>@string/item2</item>
+ </string-array>
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/typography.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/typography.xml
new file mode 100644
index 0000000..1dd4845
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/typography.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="home_title">Home 'Sample'</string>
+ <string name="show_all_apps">"All"</string>
+ <string name="show_all_apps2">Show "All"</string>
+ <string name="escaped">Skip \"All\"</string>
+ <string name="single">Android's</string>
+ <string name="copyright">(c) 2011</string>
+ <string name="badquotes1">`First'</string>
+ <string name="badquotes2">``second''</string>
+ <string name="notbadquotes">Type Option-` then 'Escape'</string>
+ <string name="fraction1">5 1/2 times</string>
+ <string name="fraction4">1/4 times</string>
+ <string name="notfraction">51/2 times, 1/20</string>
+ <string name="ellipsis">40 times...</string>
+ <string name="notellipsis">40 times.......</string>
+ <string name="ndash">For ages 3-5</string>
+ <string name="ndash2">Copyright 2007 - 2011</string>
+ <string name="nontndash">x-y</string>
+ <string name="mdash">Not found -- please try again</string>
+ <string name="nontndash">----</string>
+ <string name="notdirectional">A's and B's</string>
+ <string-array name="typography">
+ <item>Ages 3-5</item>
+ <item>Age 5 1/2</item>
+ </string-array>
+ <string name="ndash">X Y Z: 10 10 -1</string>
+</resources>
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/typos.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/typos.xml
new file mode 100644
index 0000000..dd24812
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/typos.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- No typos -->
+ <string name="s1">Home Sample</string>
+ <!-- Plain typos -->
+ <string name="s2">Andriod activites!</string>
+ <!-- Make capitalization match typo -->
+ <string name="s3"> (Cmoputer </string>
+ <!-- Markup indirection -->
+ <string name="s4"><b>throught</b></string>
+ <!-- Typo, match capitalized -->
+ <string name="s5">Seach</string>
+ <!-- random words, shouldn't flag -->
+ <string name="s6">abcdefg qwerty asdf jklm</string>
+ <!-- typo, but should only match when capitalized -->
+ <string name="s7">Tuscon tuscon</string>
+ <!-- case changes only: valid -->
+ <string name="s8">OK Cancel dialog with a long message</string>
+ <!-- case changes only: invalid -->
+ <string name="dlg_button_ok">Ok</string>
+ <!-- escaped separator -->
+ <string name="issue39599">"Please take a moment\nto rate ^1"</string>
+ <!-- escaped separator 2 -->
+ <string name="issue39599_2">"\nto</string>
+</resources> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/my/pkg/Test.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/my/pkg/Test.java.txt
new file mode 100644
index 0000000..3905b8c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/my/pkg/Test.java.txt
@@ -0,0 +1,10 @@
+package my.pgk;
+
+class Test {
+ private static String s = " R.id.button1 \" "; // R.id.button1 should not be considered referenced
+ static {
+ System.out.println(R.id.button2);
+ char c = '"';
+ System.out.println(R.id.linearLayout1);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/pkg1/Class1.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/pkg1/Class1.java.txt
new file mode 100644
index 0000000..193ff3c
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/pkg1/Class1.java.txt
@@ -0,0 +1,29 @@
+package pkg1;
+
+public class Class1 {
+ void method() {
+ }
+
+ void method2(int foo) {
+ }
+
+ void method3() {
+ }
+
+ void method4() {
+ }
+
+ void method5() {
+ }
+
+ void method6() {
+ }
+
+ void method7() {
+ }
+
+ public static class Class4 extends Class1 {
+ void method() { // Not an error: same package
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/pkg2/Class2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/pkg2/Class2.java.txt
new file mode 100644
index 0000000..651c021
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/pkg2/Class2.java.txt
@@ -0,0 +1,33 @@
+package pkg2;
+
+import android.annotation.SuppressLint;
+import pkg1.Class1;
+
+public class Class2 extends Class1 {
+ void method() { // Flag this as an accidental override
+ }
+
+ void method2(String foo) { // not an override: different signature
+ }
+
+ static void method4() { // not an override: static
+ }
+
+ private void method3() { // not an override: private
+ }
+
+ protected void method5() { // not an override: protected
+ }
+
+ public void method6() { // not an override: public
+ }
+
+ @SuppressLint("DalvikOverride")
+ public void method7() { // suppressed: no warning
+ }
+
+ public class Class3 extends Object {
+ void method() { // Not an override: not a subclass
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionBarTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionBarTest.java.txt
new file mode 100644
index 0000000..217f3b6
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionBarTest.java.txt
@@ -0,0 +1,14 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.view.Menu;
+import android.view.MenuInflater;
+
+public class ActionBarTest extends Activity {
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.menu, menu);
+ return true;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionTest1.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionTest1.java.txt
new file mode 100644
index 0000000..deeffde
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionTest1.java.txt
@@ -0,0 +1,9 @@
+package test.pkg;
+
+import android.view.MenuItem;
+
+public class ActionTest1 {
+ public void foo() {
+ System.out.println(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionTest1_ignore.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionTest1_ignore.java.txt
new file mode 100644
index 0000000..5fea6be
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionTest1_ignore.java.txt
@@ -0,0 +1,10 @@
+package test.pkg;
+
+import android.view.MenuItem;
+
+public class ActionTest1 {
+ @SuppressLint("AlwaysShowAction")
+ public void foo() {
+ System.out.println(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionTest2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionTest2.java.txt
new file mode 100644
index 0000000..2d5df6f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ActionTest2.java.txt
@@ -0,0 +1,9 @@
+package test.pkg;
+
+import android.view.MenuItem;
+
+public class ActionTest2 {
+ public void foo() {
+ System.out.println(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/BadImport.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/BadImport.java.txt
new file mode 100644
index 0000000..f5b4dd0
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/BadImport.java.txt
@@ -0,0 +1,9 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.R;
+import android.widget.*;
+
+public class BadImport {
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/CustomViewTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/CustomViewTest.java.txt
new file mode 100644
index 0000000..1862ccc
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/CustomViewTest.java.txt
@@ -0,0 +1,6 @@
+package test.pkg;
+
+import test.pkg.Intermediate.IntermediateCustomV;
+
+public class CustomViewTest extends IntermediateCustomV {
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/Foo.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/Foo.java.txt
new file mode 100644
index 0000000..6e16a72
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/Foo.java.txt
@@ -0,0 +1,7 @@
+// http://code.google.com/p/projectlombok/issues/detail?id=415
+package test.pkg;
+public class X {
+ public void X(Y parent) {
+ parent.new Z(parent.getW()).execute();
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/Hidden.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/Hidden.java.txt
new file mode 100644
index 0000000..847cd88
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/Hidden.java.txt
@@ -0,0 +1,14 @@
+package test.pkg;
+
+public class Hidden {
+ // Innocent comment...?
+ /* \u002a\u002f static { System.out.println("I'm executed on class load"); } \u002f\u002a */
+ /* \u002A\U002F static { System.out.println("I'm executed on class load"); } \u002f\u002a */
+ /* Normal \\u002A\U002F */ // OK
+ static {
+ String s = "\u002a\u002f"; // OK
+ }
+ // STOPSHIP
+ /* We must STOPSHIP! */
+ String x = "STOPSHIP"; // OK
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ImportFrameActivity.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ImportFrameActivity.java.txt
new file mode 100644
index 0000000..510dadc
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ImportFrameActivity.java.txt
@@ -0,0 +1,13 @@
+package test.pkg;
+
+import foo.bar.R;
+import android.app.Activity;
+import android.os.Bundle;
+
+public class ImportFrameActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.simple);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/InflaterTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/InflaterTest.java.txt
new file mode 100644
index 0000000..5a4e346
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/InflaterTest.java.txt
@@ -0,0 +1,65 @@
+package test.pkg;
+
+import com.example.includetest.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+@SuppressWarnings("unused")
+public class InflaterTest extends Activity {
+ private LayoutInflater mInflater;
+ private View mRootView;
+
+ private LayoutInflater getInflater() {
+ if (mInflater == null) {
+ mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+ return mInflater;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ public void testInflate1() {
+ View.inflate(this, R.layout.size1, null);
+ }
+
+ public void testInflate2() {
+ mRootView = getInflater().inflate(R.layout.size2, null);
+ }
+
+ public void testInflate4() {
+ getInflater().inflate(R.layout.size3, null, false);
+ }
+
+ public void testInflate5() {
+ int mylayout = R.layout.size4;
+ getInflater().inflate(mylayout, null, false);
+ }
+
+ public void testNotNull(ViewGroup root) {
+ getInflater().inflate(R.layout.size5, root, false); // Should be flagged
+ }
+
+ public void testInflate6() {
+ int mylayout = R.layout.size7;
+ View.inflate(this, mylayout, null);
+ }
+
+ public class MyButton extends Button {
+ public MyButton(Context context) {
+ super(context);
+ }
+
+ public void test() {
+ inflate(getContext(), R.layout.size6, null);
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/JavaPerformanceTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/JavaPerformanceTest.java.txt
new file mode 100644
index 0000000..a8caccb
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/JavaPerformanceTest.java.txt
@@ -0,0 +1,195 @@
+package test.pkg;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.widget.Button;
+/** Some test data for the JavaPerformanceDetector */
+@SuppressWarnings("unused")
+public class JavaPerformanceTest extends Button {
+ public JavaPerformanceTest(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ private Rect cachedRect;
+
+ @Override
+ protected void onDraw(android.graphics.Canvas canvas) {
+ super.onDraw(canvas);
+
+ // Various allocations:
+ new String("foo");
+ String s = new String("bar");
+
+ // This one should not be reported:
+ @SuppressLint("DrawAllocation")
+ Integer i = new Integer(5);
+
+ // Cached object initialized lazily: should not complain about these
+ if (cachedRect == null) {
+ cachedRect = new Rect(0, 0, 100, 100);
+ }
+ if (cachedRect == null || cachedRect.width() != 50) {
+ cachedRect = new Rect(0, 0, 50, 100);
+ }
+
+ boolean b = Boolean.valueOf(true); // auto-boxing
+ dummy(1, 2);
+
+ // Non-allocations
+ super.animate();
+ dummy2(1, 2);
+ int x = 4 + '5';
+
+ // This will involve allocations, but we don't track
+ // inter-procedural stuff here
+ someOtherMethod();
+ }
+
+ void dummy(Integer foo, int bar) {
+ dummy2(foo, bar);
+ }
+
+ void dummy2(int foo, int bar) {
+ }
+
+ void someOtherMethod() {
+ // Allocations are okay here
+ new String("foo");
+ String s = new String("bar");
+ boolean b = Boolean.valueOf(true); // auto-boxing
+
+ // Sparse array candidates
+ Map<Integer, String> myMap = new HashMap<Integer, String>();
+ // Should use SparseBooleanArray
+ Map<Integer, Boolean> myBoolMap = new HashMap<Integer, Boolean>();
+ // Should use SparseIntArray
+ Map<Integer, Integer> myIntMap = new java.util.HashMap<Integer, Integer>();
+
+ // This one should not be reported:
+ @SuppressLint("UseSparseArrays")
+ Map<Integer, Object> myOtherMap = new HashMap<Integer, Object>();
+ }
+
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec,
+ boolean x) { // wrong signature
+ new String("not an error");
+ }
+
+ protected void onMeasure(int widthMeasureSpec) { // wrong signature
+ new String("not an error");
+ }
+
+ protected void onLayout(boolean changed, int left, int top, int right,
+ int bottom, int wrong) { // wrong signature
+ new String("not an error");
+ }
+
+ protected void onLayout(boolean changed, int left, int top, int right) {
+ // wrong signature
+ new String("not an error");
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right,
+ int bottom) {
+ new String("flag me");
+ }
+
+ @SuppressWarnings("null") // not real code
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ new String("flag me");
+
+ // Forbidden factory methods:
+ Bitmap.createBitmap(100, 100, null);
+ android.graphics.Bitmap.createScaledBitmap(null, 100, 100, false);
+ BitmapFactory.decodeFile(null);
+ Canvas canvas = null;
+ canvas.getClipBounds(); // allocates on your behalf
+ canvas.getClipBounds(null); // NOT an error
+
+ final int layoutWidth = getWidth();
+ final int layoutHeight = getHeight();
+ if (mAllowCrop && (mOverlay == null || mOverlay.getWidth() != layoutWidth ||
+ mOverlay.getHeight() != layoutHeight)) {
+ mOverlay = Bitmap.createBitmap(layoutWidth, layoutHeight, Bitmap.Config.ARGB_8888);
+ mOverlayCanvas = new Canvas(mOverlay);
+ }
+
+ if (widthMeasureSpec == 42) {
+ throw new IllegalStateException("Test"); // NOT an allocation
+ }
+
+ // More lazy init tests
+ boolean initialized = false;
+ if (!initialized) {
+ new String("foo");
+ initialized = true;
+ }
+
+ // NOT lazy initialization
+ if (!initialized || mOverlay == null) {
+ new String("foo");
+ }
+ }
+
+ void factories() {
+ Integer i1 = new Integer(42);
+ Long l1 = new Long(42L);
+ Boolean b1 = new Boolean(true);
+ Character c1 = new Character('c');
+ Float f1 = new Float(1.0f);
+ Double d1 = new Double(1.0);
+
+ // The following should not generate errors:
+ Object i2 = new foo.bar.Integer(42);
+ Integer i3 = Integer.valueOf(42);
+ }
+
+ private boolean mAllowCrop;
+ private Canvas mOverlayCanvas;
+ private Bitmap mOverlay;
+
+ @Override
+ public void layout(int l, int t, int r, int b) {
+ // Using "this." to reference fields
+ if (this.shader == null)
+ this.shader = new LinearGradient(0, 0, getWidth(), 0, GRADIENT_COLORS, null,
+ TileMode.REPEAT);
+ }
+
+ @Override
+ public void layout(int l, int t, int r, int b) {
+ int width = getWidth();
+ int height = getHeight();
+
+ if ((shader == null) || (lastWidth != width) || (lastHeight != height))
+ {
+ lastWidth = width;
+ lastHeight = height;
+
+ shader = new LinearGradient(0, 0, width, 0, GRADIENT_COLORS, null, TileMode.REPEAT);
+ }
+ }
+
+ @Override
+ public void layout(int l, int t, int r, int b) {
+ if ((shader == null) || (lastWidth != getWidth()) || (lastHeight != getHeight())) {
+ }
+ }
+
+ public void inefficientSparseArray() {
+ new SparseArray<Integer>(); // Use SparseIntArray instead
+ new SparseArray<Long>(); // Use SparseLongArray instead
+ new SparseArray<Boolean>(); // Use SparseBooleanArray instead
+ new SparseArray<Object>(); // OK
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/NonInternationalizedSmsDetectorTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/NonInternationalizedSmsDetectorTest.java.txt
new file mode 100644
index 0000000..354f5bf
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/NonInternationalizedSmsDetectorTest.java.txt
@@ -0,0 +1,20 @@
+package foo.bar;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.telephony.SmsManager;
+
+public class NonInternationalizedSmsDetectorTest {
+ private void sendLocalizedMessage(Context context) {
+ // Don't warn here
+ SmsManager sms = SmsManager.getDefault();
+ sms.sendTextMessage("+1234567890", null, null, null, null);
+ }
+
+ private void sendAlternativeCountryPrefix(Context context) {
+ // Do warn here
+ SmsManager sms = SmsManager.getDefault();
+ sms.sendMultipartTextMessage("001234567890", null, null, null, null);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/NotificationTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/NotificationTest.java.txt
new file mode 100644
index 0000000..b03f7a8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/NotificationTest.java.txt
@@ -0,0 +1,39 @@
+package test.pkg;
+
+import android.app.Notification;
+import android.app.Notification.Builder;
+import android.content.Context;
+import android.graphics.Bitmap;
+
+@SuppressWarnings({ "deprecation", "unused", "javadoc" })
+class NotificationTest {
+ public void test1() {
+ Notification notification = new Notification(R.drawable.icon1, "Test1", 0);
+ }
+
+ public void test2() {
+ int resource = R.drawable.icon2;
+ Notification notification = new Notification(resource, "Test1", 0);
+ }
+
+ public void test3() {
+ int icon = R.drawable.icon3;
+ CharSequence tickerText = "Hello";
+ long when = System.currentTimeMillis();
+ Notification notification = new Notification(icon, tickerText, when);
+ }
+
+ public void test4(Context context, String sender, String subject, Bitmap bitmap) {
+ Notification notification = new Notification.Builder(context)
+ .setContentTitle("New mail from " + sender.toString())
+ .setContentText(subject).setSmallIcon(R.drawable.icon4)
+ .setLargeIcon(bitmap).build();
+ }
+
+ public void test5(Context context, String sender, String subject, Bitmap bitmap) {
+ Notification notification = new Builder(context)
+ .setContentTitle("New mail from " + sender.toString())
+ .setContentText(subject).setSmallIcon(R.drawable.icon5)
+ .setLargeIcon(bitmap).build();
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/PasteError.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/PasteError.java.txt
new file mode 100644
index 0000000..b12b56b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/PasteError.java.txt
@@ -0,0 +1,109 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.view.View;
+
+public class PasteError extends Activity {
+ protected void ok() {
+ Button button1 = (Button) findViewById(R.id.textView1);
+ mView2 = findViewById(R.id.textView2);
+ View view3 = findViewById(R.id.activity_main);
+ }
+
+ protected void error() {
+ View view1 = findViewById(R.id.textView1);
+ View view2 = findViewById(R.id.textView1);
+ View view3 = findViewById(R.id.textView2);
+ }
+
+ protected void ok2() {
+ View view1;
+ if (true) {
+ view1 = findViewById(R.id.textView1);
+ } else {
+ view1 = findViewById(R.id.textView1);
+ }
+ }
+
+ @SuppressLint("CutPasteId")
+ protected void suppressed() {
+ View view1 = findViewById(R.id.textView1);
+ View view2 = findViewById(R.id.textView1);
+ }
+
+ private void ok3() {
+ if (view == null || view.findViewById(R.id.city_name) == null) {
+ view = mInflater.inflate(R.layout.city_list_item, parent, false);
+ }
+ TextView name = (TextView) view.findViewById(R.id.city_name);
+ }
+
+ private void ok4() {
+ mPrevAlbumWrapper = mPrevTrackLayout.findViewById(R.id.album_wrapper);
+ mNextAlbumWrapper = mNextTrackLayout.findViewById(R.id.album_wrapper);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View listItem = convertView;
+ if (getItemViewType(position) == VIEW_TYPE_HEADER) {
+ TextView header = (TextView) listItem.findViewById(R.id.name);
+ } else if (getItemViewType(position) == VIEW_TYPE_BOOLEAN) {
+ TextView filterName = (TextView) listItem.findViewById(R.id.name);
+ } else {
+ TextView filterName = (TextView) listItem.findViewById(R.id.name);
+ }
+ }
+
+ protected void ok_branch_1() {
+ if (true) {
+ view1 = findViewById(R.id.textView1);
+ } else {
+ view2 = findViewById(R.id.textView1);
+ }
+ }
+
+ protected void error_branch_1() {
+ if (true) {
+ view1 = findViewById(R.id.textView1);
+ }
+ if (true) {
+ view2 = findViewById(R.id.textView1);
+ }
+ }
+
+ protected void error_branch_2() {
+ view1 = findViewById(R.id.textView1);
+ if (true) {
+ view2 = findViewById(R.id.textView1);
+ }
+ }
+
+ protected void error_branch_3() {
+ view1 = findViewById(R.id.textView1);
+ if (true) {
+ } else {
+ view2 = findViewById(R.id.textView1);
+ }
+ }
+
+ protected void error_branch_4() {
+ view1 = findViewById(R.id.textView1);
+ if (true) {
+ } else {
+ if (true) {
+ view2 = findViewById(R.id.textView1);
+ }
+ }
+ }
+
+ protected void ok_branch_2() {
+ if (true) {
+ view1 = findViewById(R.id.textView1);
+ } else {
+ if (true) {
+ view2 = findViewById(R.id.textView1);
+ }
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SdCardTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SdCardTest.java.txt
new file mode 100644
index 0000000..2087857
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SdCardTest.java.txt
@@ -0,0 +1,36 @@
+package test.pkg;
+
+import java.io.File;
+
+import android.content.Intent;
+import android.net.Uri;
+
+/**
+ * Ignore comments - create("/sdcard/foo")
+ */
+public class SdCardTest {
+ private static final boolean PROFILE_STARTUP = true;
+ private static final String SDCARD_TEST_HTML = "/sdcard/test.html";
+ public static final String SDCARD_ROOT = "/sdcard";
+ public static final String PACKAGES_PATH = "/sdcard/o/packages/";
+ File deviceDir = new File("/sdcard/vr");
+
+ public SdCardTest() {
+ if (PROFILE_STARTUP) {
+ android.os.Debug.startMethodTracing("/sdcard/launcher");
+ }
+ if (new File("/sdcard").exists()) {
+ }
+ String FilePath = "/sdcard/" + new File("test");
+ System.setProperty("foo.bar", "file://sdcard");
+
+
+ Intent intent = new Intent(Intent.ACTION_PICK);
+ intent.setDataAndType(Uri.parse("file://sdcard/foo.json"), "application/bar-json");
+ intent.putExtra("path-filter", "/sdcard(/.+)*");
+ intent.putExtra("start-dir", "/sdcard");
+ String mypath = "/data/data/foo";
+ String base = "/data/data/foo.bar/test-profiling";
+ String s = "file://sdcard/foo";
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SetJavaScriptEnabled.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SetJavaScriptEnabled.java.txt
new file mode 100644
index 0000000..ad8383a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SetJavaScriptEnabled.java.txt
@@ -0,0 +1,28 @@
+package com.company.something;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.webkit.WebView;
+
+public class HelloWebApp extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ WebView webView = (WebView)findViewById(R.id.webView);
+ webView.getSettings().setJavaScriptEnabled(true); // bad
+ webView.getSettings().setJavaScriptEnabled(false); // good
+ webView.loadUrl("file:///android_asset/www/index.html");
+ }
+
+ // Test Suppress
+ // Constructor: See issue 35588
+ @SuppressLint("SetJavaScriptEnabled")
+ public HelloWebApp() {
+ WebView webView = (WebView)findViewById(R.id.webView);
+ webView.getSettings().setJavaScriptEnabled(true); // bad
+ webView.getSettings().setJavaScriptEnabled(false); // good
+ webView.loadUrl("file:///android_asset/www/index.html");
+ }
+} \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest.java.txt
new file mode 100644
index 0000000..5261e34
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest.java.txt
@@ -0,0 +1,66 @@
+package foo.bar;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.widget.Toast;
+
+public class SharedPrefsText {
+ // OK 1
+ public void onCreate1(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString("foo", "bar");
+ editor.putInt("bar", 42);
+ editor.commit();
+ }
+
+ // OK 2
+ public void onCreate2(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString("foo", "bar");
+ editor.putInt("bar", 42);
+ if (apply) {
+ editor.apply();
+ }
+ }
+
+ // OK 3
+ public boolean test1(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString("foo", "bar");
+ editor.putInt("bar", 42);
+ return editor.apply();
+ }
+
+ // Not a bug
+ public void test(Foo foo) {
+ Bar bar1 = foo.edit();
+ Bar bar2 = Foo.edit();
+ Bar bar3 = edit();
+ SharedPreferences.Editor editor = preferences.edit(42);
+ apply();
+ }
+
+ // Bug
+ public void bug1(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString("foo", "bar");
+ editor.putInt("bar", 42);
+ }
+
+ // Constructor test
+ public SharedPrefsText(Context context) {
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString("foo", "bar");
+ }
+ }
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest2.java.txt
new file mode 100644
index 0000000..20c3a21
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest2.java.txt
@@ -0,0 +1,19 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+
+@SuppressWarnings("unused")
+public class SharedPrefsTest2 extends Activity {
+ public void test1(SharedPreferences preferences) {
+ SharedPreferences.Editor editor = preferences.edit();
+ }
+
+ public void test2(SharedPreferences preferences) {
+ Editor editor = preferences.edit();
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest3.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest3.java.txt
new file mode 100644
index 0000000..e5baa00
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest3.java.txt
@@ -0,0 +1,15 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.*;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+
+@SuppressWarnings("unused")
+public class SharedPrefsTest3 extends Activity {
+ public void test(SharedPreferences preferences) {
+ Editor editor = preferences.edit();
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest4.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest4.java.txt
new file mode 100644
index 0000000..28de959
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest4.java.txt
@@ -0,0 +1,15 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.SharedPreferences;
+import foo.bar.Editor;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+
+@SuppressWarnings("unused")
+public class SharedPrefsTest4 extends Activity {
+ public void test(SharedPreferences preferences) {
+ Editor editor = preferences.edit();
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest5.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest5.java.txt
new file mode 100644
index 0000000..f005162
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest5.java.txt
@@ -0,0 +1,54 @@
+package test.pkg;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.preference.PreferenceManager;
+
+@SuppressWarnings("unused")
+class SharedPrefsTest5 {
+ SharedPreferences mPreferences;
+ private static final String PREF_FOO = "foo";
+ private static final String PREF_BAZ = "bar";
+
+ private void wrong() {
+ // Field reference to preferences
+ mPreferences.edit().putString(PREF_FOO, "bar");
+ mPreferences.edit().remove(PREF_BAZ).remove(PREF_FOO);
+ }
+
+ private void ok() {
+ mPreferences.edit().putString(PREF_FOO, "bar").commit();
+ mPreferences.edit().remove(PREF_BAZ).remove(PREF_FOO).commit();
+ }
+
+ private void wrong2(SharedPreferences preferences) {
+ preferences.edit().putString(PREF_FOO, "bar");
+ preferences.edit().remove(PREF_BAZ).remove(PREF_FOO);
+ }
+
+ private void wrong3(Context context) {
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+ preferences.edit().putString(PREF_FOO, "bar");
+ preferences.edit().remove(PREF_BAZ).remove(PREF_FOO);
+ }
+
+ private void wrong4(Context context) {
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+ Editor editor = preferences.edit().putString(PREF_FOO, "bar");
+ }
+
+ private void ok2(Context context) {
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+ preferences.edit().putString(PREF_FOO, "bar").commit();
+ }
+
+ private final SharedPreferences mPrefs;
+
+ public void ok3() {
+ final SharedPreferences.Editor editor = mPrefs.edit().putBoolean(
+ PREF_FOO, true);
+ editor.putString(PREF_BAZ, "");
+ editor.apply();
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormat2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormat2.java.txt
new file mode 100644
index 0000000..a09e44b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormat2.java.txt
@@ -0,0 +1,14 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class StringFormat2 extends Activity {
+ public static final String buildUserAgent(Context context) {
+ StringBuilder arg = new StringBuilder();
+ // Snip
+ final String base = context.getResources().getText(R.string.web_user_agent).toString();
+ String ua = String.format(base, arg);
+ return ua;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormatActivity.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormatActivity.java.txt
new file mode 100644
index 0000000..c22828f
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormatActivity.java.txt
@@ -0,0 +1,35 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class StringFormatActivity extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ String target = "World";
+ String hello = getResources().getString(R.string.hello);
+ String output1 = String.format(hello, target);
+ String hello2 = getResources().getString(R.string.hello2);
+ String output2 = String.format(hello2, target, "How are you");
+ setContentView(R.layout.main);
+ String score = getResources().getString(R.string.score);
+ int points = 50;
+ boolean won = true;
+ String output3 = String.format(score, points);
+ String output4 = String.format(score, true); // wrong
+ String output4 = String.format(score, won); // wrong
+ String output5 = String.format(score, 75);
+ String.format(getResources().getString(R.string.hello2), target, "How are you");
+ getResources().getString(hello2, target, "How are you");
+ getResources().getString(R.string.hello2, target, "How are you");
+ }
+
+ // Test constructor handling (issue 35588)
+ public StringFormatActivity() {
+ String target = "World";
+ String hello = getResources().getString(R.string.hello);
+ String output1 = String.format(hello, target);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormatActivity2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormatActivity2.java.txt
new file mode 100644
index 0000000..c039dce
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormatActivity2.java.txt
@@ -0,0 +1,20 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class StringFormatActivity2 extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ String target = "World";
+ getResources().getString(R.string.formattest1, "hello");
+ getResources().getString(R.string.formattest2, "hello");
+ getResources().getString(R.string.formattest3, 42);
+ getResources().getString(R.string.formattest4, 42);
+ getResources().getString(R.string.formattest5, "hello");
+ getResources().getString(R.string.formattest6, "hello");
+ getResources().getString(R.string.formattest7, "hello");
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormatActivity_ignore.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormatActivity_ignore.java.txt
new file mode 100644
index 0000000..58717dc
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/StringFormatActivity_ignore.java.txt
@@ -0,0 +1,27 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.annotations.tools.SuppressLint;
+
+public class StringFormatActivity extends Activity {
+ /** Called when the activity is first created. */
+ @SuppressLint("all")
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ String target = "World";
+ String hello = getResources().getString(R.string.hello);
+ String output1 = String.format(hello, target);
+ String hello2 = getResources().getString(R.string.hello2);
+ String output2 = String.format(hello2, target, "How are you");
+ setContentView(R.layout.main);
+ String score = getResources().getString(R.string.score);
+ int points = 50;
+ boolean won = true;
+ String output3 = String.format(score, points);
+ String output4 = String.format(score, true); // wrong
+ String output4 = String.format(score, won); // wrong
+ String output5 = String.format(score, 75);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SuppressTest5.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SuppressTest5.java.txt
new file mode 100644
index 0000000..1646216
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/SuppressTest5.java.txt
@@ -0,0 +1,57 @@
+package test.pkg;
+
+import android.annotations.tools.SuppressLint;
+
+@SuppressWarnings("unused")
+public class SuppressTest5 {
+ private String suppressVariable() {
+ @SuppressLint("SdCardPath")
+ String string = "/sdcard/mypath1";
+ return string;
+ }
+
+ @SuppressLint("SdCardPath")
+ private String suppressMethod() {
+ String string = "/sdcard/mypath2";
+ return string;
+ }
+
+ @SuppressLint("SdCardPath")
+ private static class SuppressClass {
+ private String suppressMethod() {
+ String string = "/sdcard/mypath3";
+ return string;
+ }
+ }
+
+ private String suppressAll() {
+ @SuppressLint("all")
+ String string = "/sdcard/mypath4";
+ return string;
+ }
+
+ private String suppressCombination() {
+ @SuppressLint({"foo1", "foo2", "SdCardPath"})
+ String string = "/sdcard/mypath5";
+
+ // This is NOT annotated and *should* generate
+ // a warning (here to make sure we don't just
+ // suppress everything when we see an annotation
+ String notAnnotated = "/sdcard/mypath";
+
+ return string;
+ }
+
+ private String suppressWarnings() {
+ @SuppressWarnings("all")
+ String string = "/sdcard/mypath6";
+
+ @SuppressWarnings("SdCardPath")
+ String string2 = "/sdcard/mypath7";
+
+ return string;
+ }
+
+ @SuppressLint("SdCardPath")
+ private String supressField = "/sdcard/mypath8";
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ToastTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ToastTest.java.txt
new file mode 100644
index 0000000..ce8af3a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/ToastTest.java.txt
@@ -0,0 +1,41 @@
+package foo.bar;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.widget.Toast;
+
+public class ToastTest {
+ private Toast createToast(Context context) {
+ // Don't warn here
+ return Toast.makeText(context, "foo", Toast.LENGTH_LONG);
+ }
+
+ private void showToast(Context context) {
+ // Don't warn here
+ Toast toast = Toast.makeText(context, "foo", Toast.LENGTH_LONG);
+ System.out.println("Other intermediate code here");
+ int temp = 5 + 2;
+ toast.show();
+ }
+
+ private void showToast2(Context context) {
+ // Don't warn here
+ int duration = Toast.LENGTH_LONG;
+ Toast.makeText(context, "foo", Toast.LENGTH_LONG).show();
+ Toast.makeText(context, R.string.app_name, duration).show();
+ }
+
+ private void broken(Context context) {
+ // Errors
+ Toast.makeText(context, "foo", Toast.LENGTH_LONG);
+ Toast toast = Toast.makeText(context, R.string.app_name, 5000);
+ toast.getDuration();
+ }
+
+ // Constructor test
+ public ToastTest(Context context) {
+ Toast.makeText(context, "foo", Toast.LENGTH_LONG);
+ }
+}
+
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/UnusedReference.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/UnusedReference.java.txt
new file mode 100644
index 0000000..5d7cb87
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/UnusedReference.java.txt
@@ -0,0 +1,12 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class UnusedReference extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(test.pkg.R.layout.main);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/Utf8BomTest.java.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/Utf8BomTest.java.data
new file mode 100644
index 0000000..c8fefcd
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/Utf8BomTest.java.data
@@ -0,0 +1,5 @@
+package test.pkg;
+
+public class Utf8BomTest {
+ String s = "/sdcard/mydir";
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WorldWriteableFile.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WorldWriteableFile.java.txt
new file mode 100644
index 0000000..1e6285b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WorldWriteableFile.java.txt
@@ -0,0 +1,38 @@
+package test.pkg;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.FileNotFoundException;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.app.Activity;
+import android.os.Bundle;
+
+public class WorldWriteableFile {
+ File mFile;
+ Context mContext;
+
+ public void foo() {
+ OutputStream out = null;
+ SharedPreferences prefs = null;
+
+ boolean success = false;
+ try {
+ out = openFileOutput(mFile.getName()); // ok
+ out = openFileOutput(mFile.getName(), MODE_PRIVATE); // ok
+ out = openFileOutput(mFile.getName(), MODE_WORLD_WRITEABLE);
+ out = openFileOutput(mFile.getName(), MODE_WORLD_READABLE);
+
+ prefs = getSharedPreferences(mContext, 0); // ok
+ prefs = getSharedPreferences(mContext, MODE_PRIVATE); // ok
+ prefs = getSharedPreferences(mContext, MODE_WORLD_WRITEABLE);
+ prefs = getSharedPreferences(mContext, MODE_WORLD_READABLE);
+ // Flickr.get().downloadPhoto(params[0], Flickr.PhotoSize.LARGE,
+ // out);
+ success = true;
+ } catch (FileNotFoundException e) {
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongAnnotation.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongAnnotation.java.txt
new file mode 100644
index 0000000..6fef833
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongAnnotation.java.txt
@@ -0,0 +1,31 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.view.View;
+
+public class WrongAnnotation {
+ @Override
+ @SuppressLint("NewApi") // Valid: class-file check on method
+ public static void foobar(View view, @SuppressLint("NewApi") int foo) { // Invalid: class-file check
+ @SuppressLint("NewApi") // Invalid
+ boolean a;
+ @SuppressLint({"SdCardPath", "NewApi"}) // Invalid: class-file based check on local variable
+ boolean b;
+ @android.annotation.SuppressLint({"SdCardPath", "NewApi"}) // Invalid (FQN)
+ boolean c;
+ @SuppressLint("SdCardPath") // Valid: AST-based check
+ boolean d;
+ }
+
+ @SuppressLint("NewApi")
+ private int field1;
+
+ @SuppressLint("NewApi")
+ private int field2 = 5;
+
+ static {
+ // Local variable outside method: invalid
+ @SuppressLint("NewApi")
+ int localvar = 5;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongCastActivity.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongCastActivity.java.txt
new file mode 100644
index 0000000..45e53d0
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongCastActivity.java.txt
@@ -0,0 +1,16 @@
+package test.pkg;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.*;
+
+public class WrongCastActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.casts);
+ Button button = (Button) findViewById(R.id.button);
+ ToggleButton toggleButton = (ToggleButton) findViewById(R.id.button);
+ TextView textView = (TextView) findViewById(R.id.edittext);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongCastActivity2.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongCastActivity2.java.txt
new file mode 100644
index 0000000..7cd422a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongCastActivity2.java.txt
@@ -0,0 +1,15 @@
+package test.pkg;
+
+import android.app.*;
+import android.view.*;
+import android.widget.*;
+
+public class WrongCastActivity2 extends Activity {
+ private TextView additionalButton;
+
+ private void configureAdditionalButton(View bodyView) {
+ this.additionalButton = (TextView) bodyView
+ .findViewById(R.id.additional);
+ Object x = (AdapterView<?>) bodyView.findViewById(R.id.reminder_lead);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongCastActivity3.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongCastActivity3.java.txt
new file mode 100644
index 0000000..1701600
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongCastActivity3.java.txt
@@ -0,0 +1,11 @@
+package test.pkg;
+
+import android.app.*;
+import android.view.*;
+import android.widget.*;
+
+public class WrongCastActivity3 extends Activity {
+ private void test() {
+ final Checkable check = (Checkable) findViewById(R.id.additional);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongColor.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongColor.java.txt
new file mode 100644
index 0000000..cacd834
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/src/test/pkg/WrongColor.java.txt
@@ -0,0 +1,16 @@
+package test.pkg;
+
+import android.view.*;
+import android.widget.*;
+
+public class WrongColor {
+ public void foo(TextView textView) {
+ Paint paint2 = new Paint();
+ paint2.setColor(R.color.blue);
+ // Wrong
+ textView.setTextColor(R.color.red);
+ textView.setTextColor(android.R.color.red);
+ // OK
+ textView.setTextColor(getResources().getColor(R.color.red));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/unusedR.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/unusedR.java.txt
new file mode 100644
index 0000000..3eae431
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/unusedR.java.txt
@@ -0,0 +1,14 @@
+/* AUTO-GENERATED FILE. DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found. It
+ * should not be modified by hand.
+ */
+
+package my.pkg;
+
+public final class R {
+ public static final class attr {
+ public static final int contentId=0x7f020000;
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/ids.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/ids.xml
new file mode 100644
index 0000000..07e8ae9
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/ids.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <item name="my_id1" type="id"/>
+
+</resources>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/ignorelayout1.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/ignorelayout1.xml
new file mode 100644
index 0000000..bc6d5fd
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/ignorelayout1.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/RelativeLayout1"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <!-- my_id1 is defined in ids.xml, my_id2 is defined in main2, my_id3 does not exist -->
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@+id/button5"
+ android:layout_alignLeft="@+id/my_id2"
+ android:layout_alignParentTop="true"
+ android:layout_alignRight="@+id/my_id3"
+ android:layout_alignTop="@+id/my_id1"
+ android:text="Button"
+ tools:ignore="UnknownIdInLayout,UnknownId" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/button1"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/button2"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button4"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/button3"
+ android:text="Button" />
+
+</RelativeLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/layout1.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/layout1.xml
new file mode 100644
index 0000000..073dddd
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/layout1.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/RelativeLayout1"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <!-- my_id1 is defined in ids.xml, my_id2 is defined in main2, my_id3 does not exist -->
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@+id/button5"
+ android:layout_alignLeft="@+id/my_id2"
+ android:layout_alignParentTop="true"
+ android:layout_alignRight="@+id/my_id3"
+ android:layout_alignTop="@+id/my_id1"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/button1"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/button2"
+ android:text="Button" />
+
+ <Button
+ android:id="@+id/button4"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/button3"
+ android:text="Button" />
+
+</RelativeLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/layout2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/layout2.xml
new file mode 100644
index 0000000..54dd91a
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/wrongid/layout2.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <Button
+ android:id="@+id/my_id2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Button" />
+
+</LinearLayout>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/client/api/DefaultSdkInfoTest.java b/lint/cli/src/test/java/com/android/tools/lint/client/api/DefaultSdkInfoTest.java
new file mode 100644
index 0000000..afdc985
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/client/api/DefaultSdkInfoTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.client.api;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class DefaultSdkInfoTest extends TestCase {
+ public void testGetParentClass() {
+ DefaultSdkInfo info = new DefaultSdkInfo();
+ assertNull(info.getParentViewClass("android.view.View"));
+ assertEquals("android.view.View", info.getParentViewClass("android.view.ViewGroup"));
+ assertEquals("android.view.ViewGroup",
+ info.getParentViewClass("android.widget.LinearLayout"));
+ assertEquals("android.widget.LinearLayout",
+ info.getParentViewClass("android.widget.TableLayout"));
+ }
+
+ public void testGetParentName() {
+ DefaultSdkInfo info = new DefaultSdkInfo();
+ assertNull(info.getParentViewName("View"));
+ assertEquals("View", info.getParentViewName("ViewGroup"));
+ assertEquals("ViewGroup", info.getParentViewName("LinearLayout"));
+ assertEquals("LinearLayout", info.getParentViewName("TableLayout"));
+ }
+
+ public void testIsSubViewOf() {
+ DefaultSdkInfo info = new DefaultSdkInfo();
+ assertTrue(info.isSubViewOf("Button", "Button"));
+ assertTrue(info.isSubViewOf("TextView", "Button"));
+ assertTrue(info.isSubViewOf("TextView", "RadioButton"));
+ assertTrue(info.isSubViewOf("AdapterView", "Spinner"));
+ assertTrue(info.isSubViewOf("AdapterView<?>", "Spinner"));
+ assertFalse(info.isSubViewOf("Button", "TextView"));
+ assertFalse(info.isSubViewOf("CheckBox", "ToggleButton"));
+ assertFalse(info.isSubViewOf("ToggleButton", "CheckBox"));
+ assertTrue(info.isSubViewOf("LinearLayout", "LinearLayout"));
+ assertTrue(info.isSubViewOf("LinearLayout", "TableLayout"));
+ assertFalse(info.isSubViewOf("TableLayout", "LinearLayout"));
+ assertTrue(info.isSubViewOf("TextView", "EditText"));
+ assertFalse(info.isSubViewOf("EditText", "TextView"));
+ assertTrue(info.isSubViewOf("View", "TextView"));
+ assertFalse(info.isSubViewOf("TextView", "View"));
+ assertFalse(info.isSubViewOf("Spinner", "AdapterView<?>"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/client/api/LintClientTest.java b/lint/cli/src/test/java/com/android/tools/lint/client/api/LintClientTest.java
new file mode 100644
index 0000000..a4376d8
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/client/api/LintClientTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.client.api;
+
+import com.android.tools.lint.Main;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class LintClientTest extends TestCase {
+ public void test() throws Exception {
+ Main client = new Main();
+ int max = client.getHighestKnownApiLevel();
+ assertTrue(max >= 16);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/client/api/LintDriverTest.java b/lint/cli/src/test/java/com/android/tools/lint/client/api/LintDriverTest.java
new file mode 100644
index 0000000..f4dba93
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/client/api/LintDriverTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.client.api;
+
+import com.android.tools.lint.client.api.LintDriver.ClassEntry;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class LintDriverTest extends TestCase {
+ public void testClassEntryCompare() throws Exception {
+ ClassEntry c0 = new ClassEntry(new File("/a1/Foo.class"), null, null, null);
+ ClassEntry c1 = new ClassEntry(new File("/a1/Foo.clazz"), null, null, null);
+ ClassEntry c2 = new ClassEntry(new File("/a1/Foo$Inner1.class"), null, null, null);
+ ClassEntry c3 = new ClassEntry(new File("/a1/Foo$Inner1$Inner.class"), null, null, null);
+ ClassEntry c4 = new ClassEntry(new File("/a2/Foo$Inner2.clas"), null, null, null);
+ ClassEntry c5 = new ClassEntry(new File("/a2/Foo$Inner2.class"), null, null, null);
+
+ List<ClassEntry> expected = Arrays.asList(c0, c1, c2, c3, c4, c5);
+ List<ClassEntry> list = new ArrayList<ClassEntry>(expected);
+ Collections.sort(list);
+ assertEquals(list, list);
+
+ List<ClassEntry> list2 = Arrays.asList(c5, c4, c3, c2, c1, c0);
+ Collections.sort(list2);
+ assertEquals(expected, list2);
+
+ List<ClassEntry> list3 = Arrays.asList(c3, c0, c1, c5, c2, c4);
+ Collections.sort(list3);
+ assertEquals(expected, list3);
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/detector/api/ClassContextTest.java b/lint/cli/src/test/java/com/android/tools/lint/detector/api/ClassContextTest.java
new file mode 100644
index 0000000..71c3486
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/detector/api/ClassContextTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.detector.api;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class ClassContextTest extends TestCase {
+ public void testCreateSignature() {
+ assertEquals("foo.bar.Foo.Bar",
+ ClassContext.createSignature("foo/bar/Foo$Bar", null, null));
+ assertEquals("void foo.bar.Foo.Bar#name(int)",
+ ClassContext.createSignature("foo/bar/Foo$Bar", "name", "(I)V"));
+ assertEquals("void foo.bar.Foo.Bar#name(Integer)",
+ ClassContext.createSignature("foo/bar/Foo$Bar", "name", "(Ljava/lang/Integer;)V"));
+ }
+
+ public void testGetInternalName() {
+ assertEquals("foo/bar/Foo$Bar",
+ ClassContext.getInternalName("foo.bar.Foo.Bar"));
+ }
+
+ public void testGetFqcn() {
+ assertEquals("foo.bar.Foo.Bar", ClassContext.getFqcn("foo/bar/Foo$Bar"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/detector/api/IssueTest.java b/lint/cli/src/test/java/com/android/tools/lint/detector/api/IssueTest.java
new file mode 100644
index 0000000..c8aaf12
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/detector/api/IssueTest.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.detector.api;
+
+import static com.android.SdkConstants.AUTO_URI;
+import static com.android.tools.lint.detector.api.Issue.convertMarkup;
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class IssueTest extends TestCase {
+ public void testConvertMarkup() throws Exception {
+ assertEquals("", convertMarkup("", true));
+
+ // Normal escapes
+ assertEquals("foo bar", convertMarkup("foo bar", true));
+ assertEquals("foo<br/>\nbar", convertMarkup("foo\nbar", true));
+ assertEquals("foo<br/>\nbar", convertMarkup("foo\nbar", true));
+ assertEquals("&lt;&amp;>'\"", convertMarkup("<&>'\"", true));
+
+ // HTML Formatting
+ assertEquals("<code>@TargetApi(11)</code>, ", convertMarkup("`@TargetApi(11)`, ",
+ true));
+ assertEquals("with <code>getArguments()</code>.",
+ convertMarkup("with `getArguments()`.",
+ true));
+ assertEquals("(<code>dip</code>)", convertMarkup("(`dip`)", true));
+ assertEquals(" <code>0dp</code> ", convertMarkup(" `0dp` ", true));
+ assertEquals(
+ "resources under <code>$ANDROID_SK/platforms/android-$VERSION/data/res/.</code>",
+ convertMarkup(
+ "resources under `$ANDROID_SK/platforms/android-$VERSION/data/res/.`",
+ true));
+ assertEquals("wrong format. Instead of <code>-keepclasseswithmembernames</code> use ",
+ convertMarkup("wrong format. Instead of `-keepclasseswithmembernames` use ",
+ true));
+ assertEquals("<code>exported=false</code>)", convertMarkup("`exported=false`)",
+ true));
+ assertEquals("by setting <code>inputType=\"text\"</code>.",
+ convertMarkup("by setting `inputType=\"text\"`.", true));
+ assertEquals("* <code>View(Context context)</code><br/>\n",
+ convertMarkup("* `View(Context context)`\n", true));
+ assertEquals("The <code>@+id/</code> syntax", convertMarkup("The `@+id/` syntax",
+ true));
+ assertEquals("", convertMarkup("", true));
+ assertEquals("", convertMarkup("", true));
+ assertEquals("This is <b>bold</b>", convertMarkup("This is *bold*", true));
+ assertEquals("Visit <a href=\"http://google.com\">http://google.com</a>.",
+ convertMarkup("Visit http://google.com.", true));
+ assertEquals("This is <code>monospace</code>!", convertMarkup("This is `monospace`!",
+ true));
+ assertEquals(
+ "See <a href=\"http://developer.android.com/reference/android/view/" +
+ "WindowManager.LayoutParams.html#FLAG_KEEP_SCREEN_ON\">http://developer." +
+ "android.com/reference/android/view/WindowManager.LayoutParams.html#" +
+ "FLAG_KEEP_SCREEN_ON</a>.",
+ convertMarkup(
+ "See http://developer.android.com/reference/android/view/WindowManager.Layout" +
+ "Params.html#FLAG_KEEP_SCREEN_ON.", true));
+
+ // Text formatting
+ assertEquals("@TargetApi(11), ", convertMarkup("`@TargetApi(11)`, ", false));
+ assertEquals("with getArguments().", convertMarkup("with `getArguments()`.", false));
+ assertEquals("bold", convertMarkup("*bold*", false));
+ assertEquals("Visit http://google.com.", convertMarkup("Visit http://google.com.",
+ false));
+
+ // Corners (match at the beginning and end)
+ assertEquals("<b>bold</b>", convertMarkup("*bold*", true));
+ assertEquals("<code>monospace</code>!", convertMarkup("`monospace`!", true));
+
+ // Not formatting
+ assertEquals("a*b", convertMarkup("a*b", true));
+ assertEquals("a* b*", convertMarkup("a* b*", true));
+ assertEquals("*a *b", convertMarkup("*a *b", true));
+ assertEquals("Prefix is http:// ", convertMarkup("Prefix is http:// ", true));
+ assertEquals("", convertMarkup("", true));
+ assertEquals("", convertMarkup("", true));
+ assertEquals("", convertMarkup("", true));
+ assertEquals("", convertMarkup("", true));
+ assertEquals("This is * not * bold", convertMarkup("This is * not * bold", true));
+ assertEquals("* List item 1<br/>\n* List Item 2",
+ convertMarkup("* List item 1\n* List Item 2", true));
+ assertEquals("myhttp://foo.bar", convertMarkup("myhttp://foo.bar", true));
+ }
+
+ public void testConvertMarkup2() throws Exception {
+ // http at the end:
+ // Explanation from ManifestOrderDetector#TARGET_NEWER
+ String explanation =
+ "When your application runs on a version of Android that is more recent than your " +
+ "targetSdkVersion specifies that it has been tested with, various compatibility " +
+ "modes kick in. This ensures that your application continues to work, but it may " +
+ "look out of place. For example, if the targetSdkVersion is less than 14, your " +
+ "app may get an option button in the UI.\n" +
+ "\n" +
+ "To fix this issue, set the targetSdkVersion to the highest available value. Then " +
+ "test your app to make sure everything works correctly. You may want to consult " +
+ "the compatibility notes to see what changes apply to each version you are adding " +
+ "support for: " +
+ "http://developer.android.com/reference/android/os/Build.VERSION_CODES.html";
+
+ assertEquals(
+ "When your application runs on a version of Android that is more recent than your " +
+ "targetSdkVersion specifies that it has been tested with, various compatibility " +
+ "modes kick in. This ensures that your application continues to work, but it may " +
+ "look out of place. For example, if the targetSdkVersion is less than 14, your " +
+ "app may get an option button in the UI.<br/>\n" +
+ "<br/>\n" +
+ "To fix this issue, set the targetSdkVersion to the highest available value. Then " +
+ "test your app to make sure everything works correctly. You may want to consult " +
+ "the compatibility notes to see what changes apply to each version you are adding " +
+ "support for: " +
+ "<a href=\"http://developer.android.com/reference/android/os/Build.VERSION_CODES." +
+ "html\">http://developer.android.com/reference/android/os/Build.VERSION_CODES.html" +
+ "</a>",
+ convertMarkup(explanation, true));
+ }
+
+ public void testConvertMarkup3() throws Exception {
+ // embedded http markup test
+ // Explanation from NamespaceDetector#CUSTOMVIEW
+ String explanation =
+ "When using a custom view with custom attributes in a library project, the layout " +
+ "must use the special namespace " + AUTO_URI + " instead of a URI which includes " +
+ "the library project's own package. This will be used to automatically adjust the " +
+ "namespace of the attributes when the library resources are merged into the " +
+ "application project.";
+ assertEquals(
+ "When using a custom view with custom attributes in a library project, the layout " +
+ "must use the special namespace " +
+ "<a href=\"http://schemas.android.com/apk/res-auto\">" +
+ "http://schemas.android.com/apk/res-auto</a> " +
+ "instead of a URI which includes the library project's own package. " +
+ "This will be used to automatically adjust the namespace of the attributes when " +
+ "the library resources are merged into the application project.",
+ convertMarkup(explanation, true));
+ }
+
+ public void testConvertMarkup4() throws Exception {
+ // monospace test
+ String explanation =
+ "The manifest should contain a `<uses-sdk>` element which defines the " +
+ "minimum minimum API Level required for the application to run, " +
+ "as well as the target version (the highest API level you have tested " +
+ "the version for.)";
+
+ assertEquals(
+ "The manifest should contain a <code>&lt;uses-sdk></code> element which defines the " +
+ "minimum minimum API Level required for the application to run, " +
+ "as well as the target version (the highest API level you have tested " +
+ "the version for.)",
+ convertMarkup(explanation, true));
+ }
+
+ public void testConvertMarkup5() throws Exception {
+ // monospace and bold test
+ // From ManifestOrderDetector#MULTIPLE_USES_SDK
+ String explanation =
+ "The `<uses-sdk>` element should appear just once; the tools will *not* merge the " +
+ "contents of all the elements so if you split up the atttributes across multiple " +
+ "elements, only one of them will take effect. To fix this, just merge all the " +
+ "attributes from the various elements into a single <uses-sdk> element.";
+
+ assertEquals(
+ "The <code>&lt;uses-sdk></code> element should appear just once; the tools " +
+ "will <b>not</b> merge the " +
+ "contents of all the elements so if you split up the atttributes across multiple " +
+ "elements, only one of them will take effect. To fix this, just merge all the " +
+ "attributes from the various elements into a single &lt;uses-sdk> element.",
+ convertMarkup(explanation, true));
+ }
+
+ public void testConvertMarkup6() throws Exception {
+ // Embedded code next to attributes
+ // From AlwaysShowActionDetector#ISSUE
+ String explanation =
+ "Using `showAsAction=\"always\"` in menu XML, or `MenuItem.SHOW_AS_ACTION_ALWAYS` in "+
+ "Java code is usually a deviation from the user interface style guide." +
+ "Use `ifRoom` or the corresponding `MenuItem.SHOW_AS_ACTION_IF_ROOM` instead.\n" +
+ "\n" +
+ "If `always` is used sparingly there are usually no problems and behavior is " +
+ "roughly equivalent to `ifRoom` but with preference over other `ifRoom` " +
+ "items. Using it more than twice in the same menu is a bad idea.\n" +
+ "\n" +
+ "This check looks for menu XML files that contain more than two `always` " +
+ "actions, or some `always` actions and no `ifRoom` actions. In Java code, " +
+ "it looks for projects that contain references to `MenuItem.SHOW_AS_ACTION_ALWAYS` " +
+ "and no references to `MenuItem.SHOW_AS_ACTION_IF_ROOM`.";
+
+ assertEquals(
+ "Using <code>showAsAction=\"always\"</code> in menu XML, or " +
+ "<code>MenuItem.SHOW_AS_ACTION_ALWAYS</code> in Java code is usually a deviation " +
+ "from the user interface style guide.Use <code>ifRoom</code> or the " +
+ "corresponding <code>MenuItem.SHOW_AS_ACTION_IF_ROOM</code> instead.<br/>\n" +
+ "<br/>\n" +
+ "If <code>always</code> is used sparingly there are usually no problems and " +
+ "behavior is roughly equivalent to <code>ifRoom</code> but with preference over " +
+ "other <code>ifRoom</code> items. Using it more than twice in the same menu " +
+ "is a bad idea.<br/>\n" +
+ "<br/>\n" +
+ "This check looks for menu XML files that contain more than two <code>always</code> " +
+ "actions, or some <code>always</code> actions and no <code>ifRoom</code> actions. " +
+ "In Java code, it looks for projects that contain references to " +
+ "<code>MenuItem.SHOW_AS_ACTION_ALWAYS</code> and no references to " +
+ "<code>MenuItem.SHOW_AS_ACTION_IF_ROOM</code>.",
+ convertMarkup(explanation, true));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/detector/api/LintUtilsTest.java b/lint/cli/src/test/java/com/android/tools/lint/detector/api/LintUtilsTest.java
new file mode 100644
index 0000000..7dfa260
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/detector/api/LintUtilsTest.java
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.detector.api;
+
+import static com.android.tools.lint.detector.api.LintUtils.getLocaleAndRegion;
+import static com.android.tools.lint.detector.api.LintUtils.isImported;
+import static com.android.tools.lint.detector.api.LintUtils.splitPath;
+
+import com.android.annotations.Nullable;
+import com.android.tools.lint.LombokParser;
+import com.android.tools.lint.Main;
+import com.android.tools.lint.checks.BuiltinIssueRegistry;
+import com.android.tools.lint.client.api.IJavaParser;
+import com.android.tools.lint.client.api.LintDriver;
+import com.google.common.collect.Iterables;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+import lombok.ast.Node;
+
+@SuppressWarnings("javadoc")
+public class LintUtilsTest extends TestCase {
+ public void testPrintList() throws Exception {
+ assertEquals("foo, bar, baz",
+ LintUtils.formatList(Arrays.asList("foo", "bar", "baz"), 3));
+ assertEquals("foo, bar, baz",
+ LintUtils.formatList(Arrays.asList("foo", "bar", "baz"), 5));
+
+ assertEquals("foo, bar, baz... (3 more)",
+ LintUtils.formatList(
+ Arrays.asList("foo", "bar", "baz", "4", "5", "6"), 3));
+ assertEquals("foo... (5 more)",
+ LintUtils.formatList(
+ Arrays.asList("foo", "bar", "baz", "4", "5", "6"), 1));
+ assertEquals("foo, bar, baz",
+ LintUtils.formatList(Arrays.asList("foo", "bar", "baz"), 0));
+ }
+
+ public void testEndsWith() throws Exception {
+ assertTrue(LintUtils.endsWith("Foo", ""));
+ assertTrue(LintUtils.endsWith("Foo", "o"));
+ assertTrue(LintUtils.endsWith("Foo", "oo"));
+ assertTrue(LintUtils.endsWith("Foo", "Foo"));
+ assertTrue(LintUtils.endsWith("Foo", "FOO"));
+ assertTrue(LintUtils.endsWith("Foo", "fOO"));
+
+ assertFalse(LintUtils.endsWith("Foo", "f"));
+ }
+
+ public void testStartsWith() throws Exception {
+ assertTrue(LintUtils.startsWith("FooBar", "Bar", 3));
+ assertTrue(LintUtils.startsWith("FooBar", "BAR", 3));
+ assertTrue(LintUtils.startsWith("FooBar", "Foo", 0));
+ assertFalse(LintUtils.startsWith("FooBar", "Foo", 2));
+ }
+
+ public void testIsXmlFile() throws Exception {
+ assertTrue(LintUtils.isXmlFile(new File("foo.xml")));
+ assertTrue(LintUtils.isXmlFile(new File("foo.Xml")));
+ assertTrue(LintUtils.isXmlFile(new File("foo.XML")));
+
+ assertFalse(LintUtils.isXmlFile(new File("foo.png")));
+ assertFalse(LintUtils.isXmlFile(new File("xml")));
+ assertFalse(LintUtils.isXmlFile(new File("xml.png")));
+ }
+
+ public void testGetBasename() throws Exception {
+ assertEquals("foo", LintUtils.getBaseName("foo.png"));
+ assertEquals("foo", LintUtils.getBaseName("foo.9.png"));
+ assertEquals(".foo", LintUtils.getBaseName(".foo"));
+ }
+
+ public void testEditDistance() {
+ assertEquals(0, LintUtils.editDistance("kitten", "kitten"));
+
+ // editing kitten to sitting has edit distance 3:
+ // replace k with s
+ // replace e with i
+ // append g
+ assertEquals(3, LintUtils.editDistance("kitten", "sitting"));
+
+ assertEquals(3, LintUtils.editDistance("saturday", "sunday"));
+ assertEquals(1, LintUtils.editDistance("button", "bitton"));
+ assertEquals(6, LintUtils.editDistance("radiobutton", "bitton"));
+ }
+
+ public void testSplitPath() throws Exception {
+ assertTrue(Arrays.equals(new String[] { "/foo", "/bar", "/baz" },
+ Iterables.toArray(splitPath("/foo:/bar:/baz"), String.class)));
+
+ assertTrue(Arrays.equals(new String[] { "/foo", "/bar" },
+ Iterables.toArray(splitPath("/foo;/bar"), String.class)));
+
+ assertTrue(Arrays.equals(new String[] { "/foo", "/bar:baz" },
+ Iterables.toArray(splitPath("/foo;/bar:baz"), String.class)));
+
+ assertTrue(Arrays.equals(new String[] { "\\foo\\bar", "\\bar\\foo" },
+ Iterables.toArray(splitPath("\\foo\\bar;\\bar\\foo"), String.class)));
+
+ assertTrue(Arrays.equals(new String[] { "${sdk.dir}\\foo\\bar", "\\bar\\foo" },
+ Iterables.toArray(splitPath("${sdk.dir}\\foo\\bar;\\bar\\foo"),
+ String.class)));
+
+ assertTrue(Arrays.equals(new String[] { "${sdk.dir}/foo/bar", "/bar/foo" },
+ Iterables.toArray(splitPath("${sdk.dir}/foo/bar:/bar/foo"),
+ String.class)));
+
+ assertTrue(Arrays.equals(new String[] { "C:\\foo", "/bar" },
+ Iterables.toArray(splitPath("C:\\foo:/bar"), String.class)));
+ }
+
+ public void testCommonParen1() {
+ assertEquals(new File("/a"), (LintUtils.getCommonParent(
+ new File("/a/b/c/d/e"), new File("/a/c"))));
+ assertEquals(new File("/a"), (LintUtils.getCommonParent(
+ new File("/a/c"), new File("/a/b/c/d/e"))));
+
+ assertEquals(new File("/"), LintUtils.getCommonParent(
+ new File("/foo/bar"), new File("/bar/baz")));
+ assertEquals(new File("/"), LintUtils.getCommonParent(
+ new File("/foo/bar"), new File("/")));
+ assertNull(LintUtils.getCommonParent(
+ new File("C:\\Program Files"), new File("F:\\")));
+ assertNull(LintUtils.getCommonParent(
+ new File("C:/Program Files"), new File("F:/")));
+
+ assertEquals(new File("/foo/bar/baz"), LintUtils.getCommonParent(
+ new File("/foo/bar/baz"), new File("/foo/bar/baz")));
+ assertEquals(new File("/foo/bar"), LintUtils.getCommonParent(
+ new File("/foo/bar/baz"), new File("/foo/bar")));
+ assertEquals(new File("/foo/bar"), LintUtils.getCommonParent(
+ new File("/foo/bar/baz"), new File("/foo/bar/foo")));
+ assertEquals(new File("/foo"), LintUtils.getCommonParent(
+ new File("/foo/bar"), new File("/foo/baz")));
+ assertEquals(new File("/foo"), LintUtils.getCommonParent(
+ new File("/foo/bar"), new File("/foo/baz")));
+ assertEquals(new File("/foo/bar"), LintUtils.getCommonParent(
+ new File("/foo/bar"), new File("/foo/bar/baz")));
+ }
+
+ public void testCommonParent2() {
+ assertEquals(new File("/"), LintUtils.getCommonParent(
+ Arrays.asList(new File("/foo/bar"), new File("/bar/baz"))));
+ assertEquals(new File("/"), LintUtils.getCommonParent(
+ Arrays.asList(new File("/foo/bar"), new File("/"))));
+ assertNull(LintUtils.getCommonParent(
+ Arrays.asList(new File("C:\\Program Files"), new File("F:\\"))));
+ assertNull(LintUtils.getCommonParent(
+ Arrays.asList(new File("C:/Program Files"), new File("F:/"))));
+
+ assertEquals(new File("/foo"), LintUtils.getCommonParent(
+ Arrays.asList(new File("/foo/bar"), new File("/foo/baz"))));
+ assertEquals(new File("/foo"), LintUtils.getCommonParent(
+ Arrays.asList(new File("/foo/bar"), new File("/foo/baz"),
+ new File("/foo/baz/f"))));
+ assertEquals(new File("/foo/bar"), LintUtils.getCommonParent(
+ Arrays.asList(new File("/foo/bar"), new File("/foo/bar/baz"),
+ new File("/foo/bar/foo2/foo3"))));
+ }
+
+ public void testStripIdPrefix() throws Exception {
+ assertEquals("foo", LintUtils.stripIdPrefix("@+id/foo"));
+ assertEquals("foo", LintUtils.stripIdPrefix("@id/foo"));
+ assertEquals("foo", LintUtils.stripIdPrefix("foo"));
+ }
+
+ public void testIdReferencesMatch() throws Exception {
+ assertTrue(LintUtils.idReferencesMatch("@+id/foo", "@+id/foo"));
+ assertTrue(LintUtils.idReferencesMatch("@id/foo", "@id/foo"));
+ assertTrue(LintUtils.idReferencesMatch("@id/foo", "@+id/foo"));
+ assertTrue(LintUtils.idReferencesMatch("@+id/foo", "@id/foo"));
+
+ assertFalse(LintUtils.idReferencesMatch("@+id/foo", "@+id/bar"));
+ assertFalse(LintUtils.idReferencesMatch("@id/foo", "@+id/bar"));
+ assertFalse(LintUtils.idReferencesMatch("@+id/foo", "@id/bar"));
+ assertFalse(LintUtils.idReferencesMatch("@+id/foo", "@+id/bar"));
+
+ assertFalse(LintUtils.idReferencesMatch("@+id/foo", "@+id/foo1"));
+ assertFalse(LintUtils.idReferencesMatch("@id/foo", "@id/foo1"));
+ assertFalse(LintUtils.idReferencesMatch("@id/foo", "@+id/foo1"));
+ assertFalse(LintUtils.idReferencesMatch("@+id/foo", "@id/foo1"));
+
+ assertFalse(LintUtils.idReferencesMatch("@+id/foo1", "@+id/foo"));
+ assertFalse(LintUtils.idReferencesMatch("@id/foo1", "@id/foo"));
+ assertFalse(LintUtils.idReferencesMatch("@id/foo1", "@+id/foo"));
+ assertFalse(LintUtils.idReferencesMatch("@+id/foo1", "@id/foo"));
+ }
+
+ private static void checkEncoding(String encoding, boolean writeBom, String lineEnding)
+ throws Exception {
+ StringBuilder sb = new StringBuilder();
+
+ // Norwegian extra vowel characters such as "latin small letter a with ring above"
+ String value = "\u00e6\u00d8\u00e5";
+ String expected = "First line." + lineEnding + "Second line." + lineEnding
+ + "Third line." + lineEnding + value + lineEnding;
+ sb.append(expected);
+ File file = File.createTempFile("getEncodingTest" + encoding + writeBom, ".txt");
+ file.deleteOnExit();
+ BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(file));
+ OutputStreamWriter writer = new OutputStreamWriter(stream, encoding);
+
+ if (writeBom) {
+ String normalized = encoding.toLowerCase().replace("-", "_");
+ if (normalized.equals("utf_8")) {
+ stream.write(0xef);
+ stream.write(0xbb);
+ stream.write(0xbf);
+ } else if (normalized.equals("utf_16")) {
+ stream.write(0xfe);
+ stream.write(0xff);
+ } else if (normalized.equals("utf_16le")) {
+ stream.write(0xff);
+ stream.write(0xfe);
+ } else if (normalized.equals("utf_32")) {
+ stream.write(0x0);
+ stream.write(0x0);
+ stream.write(0xfe);
+ stream.write(0xff);
+ } else if (normalized.equals("utf_32le")) {
+ stream.write(0xff);
+ stream.write(0xfe);
+ stream.write(0x0);
+ stream.write(0x0);
+ } else {
+ fail("Can't write BOM for encoding " + encoding);
+ }
+ }
+ writer.write(sb.toString());
+ writer.close();
+
+ String s = LintUtils.getEncodedString(new Main(), file);
+ assertEquals(expected, s);
+ }
+
+ public void testGetEncodedString() throws Exception {
+ checkEncoding("utf-8", false /*bom*/, "\n");
+ checkEncoding("UTF-8", false /*bom*/, "\n");
+ checkEncoding("UTF_16", false /*bom*/, "\n");
+ checkEncoding("UTF-16", false /*bom*/, "\n");
+ checkEncoding("UTF_16LE", false /*bom*/, "\n");
+
+ // Try BOM's
+ checkEncoding("utf-8", true /*bom*/, "\n");
+ checkEncoding("UTF-8", true /*bom*/, "\n");
+ checkEncoding("UTF_16", true /*bom*/, "\n");
+ checkEncoding("UTF-16", true /*bom*/, "\n");
+ checkEncoding("UTF_16LE", true /*bom*/, "\n");
+ checkEncoding("UTF_32", true /*bom*/, "\n");
+ checkEncoding("UTF_32LE", true /*bom*/, "\n");
+
+ // Make sure this works for \r and \r\n as well
+ checkEncoding("UTF-16", false /*bom*/, "\r");
+ checkEncoding("UTF_16LE", false /*bom*/, "\r");
+ checkEncoding("UTF-16", false /*bom*/, "\r\n");
+ checkEncoding("UTF_16LE", false /*bom*/, "\r\n");
+ checkEncoding("UTF-16", true /*bom*/, "\r");
+ checkEncoding("UTF_16LE", true /*bom*/, "\r");
+ checkEncoding("UTF_32", true /*bom*/, "\r");
+ checkEncoding("UTF_32LE", true /*bom*/, "\r");
+ checkEncoding("UTF-16", true /*bom*/, "\r\n");
+ checkEncoding("UTF_16LE", true /*bom*/, "\r\n");
+ checkEncoding("UTF_32", true /*bom*/, "\r\n");
+ checkEncoding("UTF_32LE", true /*bom*/, "\r\n");
+ }
+
+ public void testGetLocaleAndRegion() throws Exception {
+ assertNull(getLocaleAndRegion(""));
+ assertNull(getLocaleAndRegion("values"));
+ assertNull(getLocaleAndRegion("values-xlarge-port"));
+ assertEquals("en", getLocaleAndRegion("values-en"));
+ assertEquals("pt-rPT", getLocaleAndRegion("values-pt-rPT-nokeys"));
+ assertEquals("zh-rCN", getLocaleAndRegion("values-zh-rCN-keyshidden"));
+ assertEquals("ms", getLocaleAndRegion("values-ms-keyshidden"));
+ }
+
+ public void testIsImported() throws Exception {
+ assertFalse(isImported(getCompilationUnit(
+ "package foo.bar;\n" +
+ "class Foo {\n" +
+ "}\n"),
+ "android.app.Activity"));
+
+ assertTrue(isImported(getCompilationUnit(
+ "package foo.bar;\n" +
+ "import foo.bar.*;\n" +
+ "import android.app.Activity;\n" +
+ "import foo.bar.Baz;\n" +
+ "class Foo {\n" +
+ "}\n"),
+ "android.app.Activity"));
+
+ assertTrue(isImported(getCompilationUnit(
+ "package foo.bar;\n" +
+ "import android.app.Activity;\n" +
+ "class Foo {\n" +
+ "}\n"),
+ "android.app.Activity"));
+
+ assertTrue(isImported(getCompilationUnit(
+ "package foo.bar;\n" +
+ "import android.app.*;\n" +
+ "class Foo {\n" +
+ "}\n"),
+ "android.app.Activity"));
+
+ assertFalse(isImported(getCompilationUnit(
+ "package foo.bar;\n" +
+ "import android.app.*;\n" +
+ "import foo.bar.Activity;\n" +
+ "class Foo {\n" +
+ "}\n"),
+ "android.app.Activity"));
+ }
+
+ private Node getCompilationUnit(String javaSource) {
+ IJavaParser parser = new LombokParser();
+ TestContext context = new TestContext(javaSource, new File("test"));
+ Node compilationUnit = parser.parseJava(context);
+ assertNotNull(javaSource, compilationUnit);
+ return compilationUnit;
+ }
+
+ private class TestContext extends JavaContext {
+ private final String mJavaSource;
+ public TestContext(String javaSource, File file) {
+ super(new LintDriver(new BuiltinIssueRegistry(),
+ new Main()), new Main().getProject(new File("dummy"), new File("dummy")),
+ null, file);
+
+ mJavaSource = javaSource;
+ }
+
+ @Override
+ @Nullable
+ public String getContents() {
+ return mJavaSource;
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/detector/api/LocationTest.java b/lint/cli/src/test/java/com/android/tools/lint/detector/api/LocationTest.java
new file mode 100644
index 0000000..6404202
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/detector/api/LocationTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.detector.api;
+
+import java.io.File;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class LocationTest extends TestCase {
+ public void testReverse() throws IOException {
+ File file1 = new File("parent/location1");
+ File file2 = new File("parent/location2");
+ File file3 = new File("parent/location3");
+ File file4 = new File("parent/location4");
+
+ Location location1 = Location.create(file1);
+ Location location2 = Location.create(file2);
+ Location location3 = Location.create(file3);
+ Location location4 = Location.create(file4);
+
+ // 1-element location list
+ assertSame(location1, Location.reverse(location1));
+ assertFalse(containsCycle(location1));
+
+ // 2-element location list
+ location1.setSecondary(location2);
+ assertSame(location2, Location.reverse(location1));
+ assertFalse(containsCycle(location2));
+ assertSame(location1, location2.getSecondary());
+
+ // 3-element location list
+ location1.setSecondary(location2);
+ location2.setSecondary(location3);
+ assertSame(location3, Location.reverse(location1));
+ assertFalse(containsCycle(location3));
+ assertSame(location2, location3.getSecondary());
+ assertSame(location1, location2.getSecondary());
+
+ // 4-element location list
+ location1.setSecondary(location2);
+ location2.setSecondary(location3);
+ location3.setSecondary(location4);
+ assertSame(location4, Location.reverse(location1));
+ assertFalse(containsCycle(location4));
+ assertSame(location3, location4.getSecondary());
+ assertSame(location2, location3.getSecondary());
+ assertSame(location1, location2.getSecondary());
+ }
+
+ public void testFaen() throws Exception {
+ File[] paths = new File[] {
+ new File("values-zh-rTW/arrays.xml"), new File("values-zh-rCN/arrays.xml"),
+ new File("values-vi/arrays.xml"), new File("values-uk/arrays.xml"),
+ new File("values-tr/arrays.xml"), new File("values-tl/arrays.xml"),
+ new File("values-th/arrays.xml"), new File("values-sv/arrays.xml"),
+ new File("values-sr/arrays.xml"), new File("values-sl/arrays.xml"),
+ new File("values-sk/arrays.xml"), new File("values-ru/arrays.xml"),
+ new File("values-ro/arrays.xml"), new File("values-rm/arrays.xml"),
+ new File("values-pt-rPT/arrays.xml"), new File("values-pt/arrays.xml"),
+ new File("values-pl/arrays.xml"), new File("values-nl/arrays.xml"),
+ new File("values-nb/arrays.xml"), new File("values-lv/arrays.xml"),
+ new File("values-lt/arrays.xml"), new File("values-ko/arrays.xml"),
+ new File("values-ja/arrays.xml"), new File("values-iw/arrays.xml"),
+ new File("values-it/arrays.xml"), new File("values-in/arrays.xml"),
+ new File("values-hu/arrays.xml"), new File("values-hr/arrays.xml"),
+ new File("values-fr/arrays.xml"), new File("values-fi/arrays.xml"),
+ new File("values-fa/arrays.xml"), new File("values-es-rUS/arrays.xml"),
+ new File("values-es/arrays.xml"), new File("values-en-rGB/arrays.xml"),
+ new File("values-el/arrays.xml"), new File("values-de/arrays.xml"),
+ new File("values-da/arrays.xml"), new File("values-cs/arrays.xml"),
+ new File("values-ca/arrays.xml"), new File("values-bg/arrays.xml"),
+ new File("values-ar/arrays.xml"), new File("values/arrays.xml")
+ };
+
+ Location last = null;
+ for (int i = paths.length - 1; i >= 0; i--) {
+ Location location = Location.create(paths[i]);
+ location.setSecondary(last);
+ last = location;
+ }
+
+ assertFalse(containsCycle(last));
+ Location.reverse(last);
+ assertFalse(containsCycle(last));
+ }
+
+ private static boolean containsCycle(Location location) {
+ // Make sure there's no cycle: iterate
+ Location a = location;
+ Location b = location;
+
+ while (true) {
+ b = b.getSecondary();
+ if (b == null) {
+ // OK! Found list end
+ return false;
+ }
+ if (b == a) {
+ return true;
+ }
+ b = b.getSecondary();
+ if (b == null) {
+ // OK! Found list end
+ return false;
+ }
+ if (b == a) {
+ return true;
+ }
+
+ a = a.getSecondary();
+ assert a != null;
+ }
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/detector/api/ScopeTest.java b/lint/cli/src/test/java/com/android/tools/lint/detector/api/ScopeTest.java
new file mode 100644
index 0000000..e95c502
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/detector/api/ScopeTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.lint.detector.api;
+
+import java.util.EnumSet;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class ScopeTest extends TestCase {
+ public void testIntersect() {
+ assertEquals(Scope.RESOURCE_FILE_SCOPE,
+ Scope.intersect(Scope.RESOURCE_FILE_SCOPE, Scope.RESOURCE_FILE_SCOPE));
+
+ assertEquals(EnumSet.of(Scope.RESOURCE_FILE),
+ Scope.intersect(
+ EnumSet.of(Scope.RESOURCE_FILE),
+ EnumSet.of(Scope.RESOURCE_FILE)));
+
+ assertEquals(EnumSet.of(Scope.RESOURCE_FILE),
+ Scope.intersect(
+ EnumSet.of(Scope.RESOURCE_FILE, Scope.JAVA_FILE),
+ EnumSet.of(Scope.RESOURCE_FILE)));
+
+ assertEquals(EnumSet.of(Scope.JAVA_FILE),
+ Scope.intersect(
+ EnumSet.of(Scope.RESOURCE_FILE, Scope.JAVA_FILE),
+ EnumSet.of(Scope.JAVA_FILE)));
+
+ assertEquals(EnumSet.of(Scope.RESOURCE_FILE),
+ Scope.intersect(
+ EnumSet.of(Scope.RESOURCE_FILE),
+ EnumSet.of(Scope.RESOURCE_FILE, Scope.JAVA_FILE)));
+
+ assertEquals(EnumSet.of(Scope.JAVA_FILE),
+ Scope.intersect(
+ EnumSet.of(Scope.JAVA_FILE),
+ EnumSet.of(Scope.RESOURCE_FILE, Scope.JAVA_FILE)));
+
+ assertTrue(Scope.intersect(
+ EnumSet.of(Scope.JAVA_FILE), EnumSet.of(Scope.RESOURCE_FILE)).isEmpty());
+ }
+}