diff options
4 files changed, 90 insertions, 1 deletions
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java index a367cd6..720c0da 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java @@ -53,7 +53,7 @@ public class BuiltinIssueRegistry extends IssueRegistry { private static final List<Issue> sIssues; static { - final int initialCapacity = 90; + final int initialCapacity = 91; List<Issue> issues = new ArrayList<Issue>(initialCapacity); issues.add(AccessibilityDetector.ISSUE); @@ -105,6 +105,7 @@ public class BuiltinIssueRegistry extends IssueRegistry { issues.add(ManifestOrderDetector.USES_SDK); issues.add(ManifestOrderDetector.MULTIPLE_USES_SDK); issues.add(ManifestOrderDetector.WRONG_PARENT); + issues.add(ManifestOrderDetector.DUPLICATE_ACTIVITY); issues.add(SecurityDetector.EXPORTED_PROVIDER); issues.add(SecurityDetector.EXPORTED_SERVICE); issues.add(SecurityDetector.OPEN_PROVIDER); diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java index ccf6e98..cf75ae5 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java @@ -19,6 +19,8 @@ package com.android.tools.lint.checks; import static com.android.tools.lint.detector.api.LintConstants.ANDROID_MANIFEST_XML; import static com.android.tools.lint.detector.api.LintConstants.ANDROID_URI; import static com.android.tools.lint.detector.api.LintConstants.ATTR_MIN_SDK_VERSION; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_NAME; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_PACKAGE; import static com.android.tools.lint.detector.api.LintConstants.ATTR_TARGET_SDK_VERSION; import static com.android.tools.lint.detector.api.LintConstants.TAG_ACTIVITY; import static com.android.tools.lint.detector.api.LintConstants.TAG_APPLICATION; @@ -39,6 +41,7 @@ import com.android.tools.lint.detector.api.Severity; import com.android.tools.lint.detector.api.Speed; import com.android.tools.lint.detector.api.XmlContext; +import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -47,6 +50,8 @@ import java.io.File; import java.util.Arrays; import java.util.Collection; import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; /** * Checks for issues in AndroidManifest files such as declaring elements in the @@ -122,6 +127,22 @@ public class ManifestOrderDetector extends Detector implements Detector.XmlScann EnumSet.of(Scope.MANIFEST)).setMoreInfo( "http://developer.android.com/guide/topics/manifest/manifest-intro.html"); //$NON-NLS-1$ + /** Missing a {@code <uses-sdk>} element */ + public static final Issue DUPLICATE_ACTIVITY = Issue.create( + "DuplicateActivity", //$NON-NLS-1$ + "Checks that an activity is registered only once in the manifest", + + "An activity should only be registered once in the manifest. If it is " + + "accidentally registered more than once, then subtle errors can occur, " + + "since attribute declarations from the two elements are not merged, so " + + "you may accidentally remove previous declarations.", + + Category.CORRECTNESS, + 5, + Severity.ERROR, + ManifestOrderDetector.class, + EnumSet.of(Scope.MANIFEST)); + /** Constructs a new {@link ManifestOrderDetector} check */ public ManifestOrderDetector() { } @@ -131,6 +152,12 @@ public class ManifestOrderDetector extends Detector implements Detector.XmlScann /** Number of times we've seen the <uses-sdk> element */ private int mSeenUsesSdk; + /** Activities we've encountered */ + private Set<String> mActivities = new HashSet<String>(); + + /** Package declared in the manifest */ + private String mPackage; + @Override public Speed getSpeed() { return Speed.FAST; @@ -196,6 +223,28 @@ public class ManifestOrderDetector extends Detector implements Detector.XmlScann tag), null); } + if (tag.equals(TAG_ACTIVITY)) { + Attr nameNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME); + if (nameNode != null) { + String name = nameNode.getValue(); + if (!name.isEmpty()) { + if (name.charAt(0) == '.') { + name = getPackage(element) + name; + } else if (name.indexOf('.') == -1) { + name = getPackage(element) + '.' + name; + } + if (mActivities.contains(name)) { + String message = String.format( + "Duplicate registration for activity %1$s", name); + context.report(DUPLICATE_ACTIVITY, context.getLocation(nameNode), + message, null); + } else { + mActivities.add(name); + } + } + } + } + return; } @@ -268,4 +317,12 @@ public class ManifestOrderDetector extends Detector implements Detector.XmlScann mSeenApplication = false; } } + + private String getPackage(Element element) { + if (mPackage == null) { + return element.getOwnerDocument().getDocumentElement().getAttribute(ATTR_PACKAGE); + } + + return mPackage; + } } diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java index 9553d78..54bb1f3 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java @@ -100,4 +100,13 @@ public class ManifestOrderDetectorTest extends AbstractCheckTest { lintProject("broken-manifest2.xml=>AndroidManifest.xml")); } + + public void testDuplicateActivity() throws Exception { + assertEquals( + "AndroidManifest.xml:16: Error: Duplicate registration for activity com.example.helloworld.HelloWorld", + + lintProject( + "duplicate-manifest.xml=>AndroidManifest.xml", + "res/values/strings.xml")); + } } diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/duplicate-manifest.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/duplicate-manifest.xml new file mode 100644 index 0000000..e1fc3c6 --- /dev/null +++ b/lint/libs/lint_checks/tests/src/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> |