diff options
author | Tor Norbye <tnorbye@google.com> | 2012-12-07 15:59:22 -0800 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2012-12-07 15:59:22 -0800 |
commit | b2610dc727355ff1fb22144226c7c47f42f4b636 (patch) | |
tree | 0138ac74b4eabc94d0807fd97604a3021e4d41a6 /lint/cli | |
parent | 3843919d1561e98d9bf66193e0e68c7ae30db4dd (diff) | |
download | sdk-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')
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=\"<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="?"\"\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 `<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=\" <uses-sdk android:minSdkVersion="8" />\"\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 "Fooo", 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="Fooo" />\"\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=\"<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="?"\"\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 `<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=\" <uses-sdk android:minSdkVersion="8" />\"\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 "Fooo", 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="Fooo" />\"\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 (–, –) ? [TypographyDashes]\n" + + " <string name=\"ndash\">For ages 3-5</string>\n" + + " ^\n" + + "res/values/typography.xml:18: Warning: Replace \"-\" with an \"en dash\" character (–, –) ? [TypographyDashes]\n" + + " <string name=\"ndash2\">Copyright 2007 - 2011</string>\n" + + " ^\n" + + "res/values/typography.xml:20: Warning: Replace \"--\" with an \"em dash\" character (—, —) ? [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 (–, –) ? [TypographyDashes]\n" + + " <item>Ages 3-5</item>\n" + + " ^\n" + + "res/values/typography.xml:15: Warning: Replace \"...\" with ellipsis character (…, …) ? [TypographyEllipsis]\n" + + " <string name=\"ellipsis\">40 times...</string>\n" + + " ^\n" + + "res/values/typography.xml:12: Warning: Use fraction character ½ (½) 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 ¼ (¼) instead of 1/4 ? [TypographyFractions]\n" + + " <string name=\"fraction4\">1/4 times</string>\n" + + " ^\n" + + "res/values/typography.xml:25: Warning: Use fraction character ½ (½) 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 (‘’, ‘ and ’) ? [TypographyQuotes]\n" + + " <string name=\"home_title\">Home 'Sample'</string>\n" + + " ^\n" + + "res/values/typography.xml:5: Warning: Replace straight quotes (\") with directional quotes (“”, “ and ”) ? [TypographyQuotes]\n" + + " <string name=\"show_all_apps2\">Show \"All\"</string>\n" + + " ^\n" + + "res/values/typography.xml:6: Warning: Replace straight quotes (\") with directional quotes (“”, “ and ”) ? [TypographyQuotes]\n" + + " <string name=\"escaped\">Skip \\\"All\\\"</string>\n" + + " ^\n" + + "res/values/typography.xml:7: Warning: Replace apostrophe (') with typographic apostrophe (’, ’) ? [TypographyQuotes]\n" + + " <string name=\"single\">Android's</string>\n" + + " ^\n" + + "res/values/typography.xml:9: Warning: Replace apostrophe (') with typographic apostrophe (’, ’) ? [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 (‘’, ‘ and ’) ? [TypographyQuotes]\n" + + " <string name=\"notbadquotes\">Type Option-` then 'Escape'</string>\n" + + " ^\n" + + "res/values/typography.xml:8: Warning: Replace (c) with copyright symbol © (©) ? [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 Binary files differnew file mode 100644 index 0000000..4e2b100 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest.class.data 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 Binary files differnew file mode 100644 index 0000000..23ef1bd --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.class.data 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew file mode 100644 index 0000000..17e10d6 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest11.class.data 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 Binary files differnew file mode 100644 index 0000000..4056133 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest12.class.data 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 Binary files differnew file mode 100644 index 0000000..32c3657 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest2.class.data 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 Binary files differnew file mode 100644 index 0000000..3d39e74 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest3.class.data 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew file mode 100644 index 0000000..b51d04a --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest4.class.data 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 Binary files differnew file mode 100644 index 0000000..ad0cd48 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest5.class.data 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 Binary files differnew file mode 100644 index 0000000..7c0f3a7 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest6.class.data 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 Binary files differnew file mode 100644 index 0000000..e9f739d --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest7.class.data 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 Binary files differnew file mode 100644 index 0000000..b92e7d9 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest8.class.data 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 Binary files differnew file mode 100644 index 0000000..f50ebab --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.class.data 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 Binary files differnew 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 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 Binary files differnew file mode 100644 index 0000000..7dc3d60 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest.class.data 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew file mode 100644 index 0000000..defae98 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/ApiTargetTest2.class.data 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 Binary files differnew file mode 100644 index 0000000..acb19e5 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/CloseTest.class.data 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 Binary files differnew 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 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 Binary files differnew file mode 100644 index 0000000..8d187da --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/Intermediate.class.data 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 Binary files differnew file mode 100644 index 0000000..60d4e81 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest1.class.data 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 Binary files differnew file mode 100644 index 0000000..fdb512b --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest2.class.data 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 Binary files differnew file mode 100644 index 0000000..23e8b5c --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest3.class.data 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 Binary files differnew file mode 100644 index 0000000..c85a4ff --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/SuppressTest4.class.data 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 Binary files differnew file mode 100644 index 0000000..fa676b9 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestEnum.class.data 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 Binary files differnew file mode 100644 index 0000000..9e74a7a --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/TestLint.class.data 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 Binary files differnew file mode 100644 index 0000000..7cbedc1 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/unsupported.jar.data 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 Binary files differnew file mode 100644 index 0000000..85ebb78 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/AbstractActivity.class.data 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 Binary files differnew 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 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 Binary files differnew file mode 100644 index 0000000..cee3058 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class1.class.data 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 Binary files differnew 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 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 Binary files differnew file mode 100644 index 0000000..1b72f03 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/Class2.class.data 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 Binary files differnew file mode 100644 index 0000000..7f9f23b --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CommentsActivity.class.data 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 Binary files differnew file mode 100644 index 0000000..d6a8ad7 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView1.class.data 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 Binary files differnew file mode 100644 index 0000000..0788ef3 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView2.class.data 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 Binary files differnew file mode 100644 index 0000000..a4b7c7d --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomView3.class.data 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 Binary files differnew file mode 100644 index 0000000..e145fbc --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/CustomViewTest.class.data 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew file mode 100644 index 0000000..6cc8387 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/FragmentTest.class.data 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 Binary files differnew file mode 100644 index 0000000..73a9947 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.class.data 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 Binary files differnew file mode 100644 index 0000000..f5ef6d1 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/GetterTest.jar.data 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew file mode 100644 index 0000000..93f9999 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/HandlerTest.class.data 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 Binary files differnew file mode 100644 index 0000000..2b10aa9 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/LocaleTest.class.data 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 Binary files differnew file mode 100644 index 0000000..6647f1c --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/MathTest.class.data 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 Binary files differnew file mode 100644 index 0000000..216a865 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/OnClickActivity.class.data 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 Binary files differnew file mode 100644 index 0000000..3236187 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/SecureRandomTest.class.data 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 Binary files differnew file mode 100644 index 0000000..d922751 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestFieldGetter.class.data 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 Binary files differnew file mode 100644 index 0000000..945742f --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider.class.data 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 Binary files differnew file mode 100644 index 0000000..0973dbe --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestProvider2.class.data 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 Binary files differnew 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 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 Binary files differnew file mode 100644 index 0000000..6180e40 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestReceiver.class.data 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 Binary files differnew file mode 100644 index 0000000..a98f7aa --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/TestService.class.data 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 Binary files differnew file mode 100644 index 0000000..f26032c --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/ViewTagTest.class.data 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 Binary files differnew file mode 100644 index 0000000..d4733e6 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity1.class.data 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 Binary files differnew file mode 100644 index 0000000..89e35c1 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity2.class.data 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 Binary files differnew file mode 100644 index 0000000..b430519 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity3.class.data 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 Binary files differnew file mode 100644 index 0000000..8905203 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity4.class.data 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 Binary files differnew file mode 100644 index 0000000..9eca365 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity5.class.data 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 Binary files differnew file mode 100644 index 0000000..51fdf69 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity6.class.data 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 Binary files differnew file mode 100644 index 0000000..289b0d3 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity7.class.data 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 Binary files differnew file mode 100644 index 0000000..5bd3ae2 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/WakelockActivity8.class.data 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 Binary files differnew file mode 100644 index 0000000..fa52dcf --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/classes.jar 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew file mode 100644 index 0000000..e51a0e8 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Bar.class.data 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew file mode 100644 index 0000000..aafcc73 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/registration/Foo.class.data 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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("<&>'\"", 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><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><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 <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()); + } +} |