Add per-node ignore handling for more lint checks

A handful of lint checks still don't support per-node suppress
checking (because the computation does not have node information at
the time when the final warnigns are produced).

This checkin uses the new location client data facility to add scope
checking for a few more of the lint checks.

Change-Id: I0ca48e91441dcd753834ad4777959f728b74ac71
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAttribute.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAttribute.java
index e3669f0..b3174d3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAttribute.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAttribute.java
@@ -35,7 +35,6 @@
 import com.android.tools.lint.checks.OverdrawDetector;
 import com.android.tools.lint.checks.StringFormatDetector;
 import com.android.tools.lint.checks.TranslationDetector;
-import com.android.tools.lint.checks.WrongIdDetector;
 
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.runtime.CoreException;
@@ -183,9 +182,7 @@
                 || id.equals(StringFormatDetector.ARG_TYPES.getId())
                 || id.equals(StringFormatDetector.ARG_COUNT.getId())
                 || id.equals(TranslationDetector.MISSING.getId())
-                || id.equals(TranslationDetector.EXTRA.getId())
-                || id.equals(WrongIdDetector.UNKNOWN_ID.getId())
-                || id.equals(WrongIdDetector.UNKNOWN_ID_LAYOUT.getId())) {
+                || id.equals(TranslationDetector.EXTRA.getId())) {
             node = document.getDocumentElement();
         }
 
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/WrongIdDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/WrongIdDetector.java
index f96baea..a664196 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/WrongIdDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/WrongIdDetector.java
@@ -179,6 +179,7 @@
                                 XmlContext xmlContext = (XmlContext) context;
                                 IDomParser parser = xmlContext.parser;
                                 Handle handle = parser.createLocationHandle(xmlContext, attr);
+                                handle.setClientData(attr);
 
                                 if (mHandles == null) {
                                     mHandles = new ArrayList<Pair<String,Handle>>();
@@ -205,7 +206,6 @@
                 boolean isBound = idDefined(mGlobalIds, id);
                 if (!isBound && checkExists && projectScope) {
                     Handle handle = pair.getSecond();
-                    Location location = handle.resolve();
                     boolean isDeclared = idDefined(mDeclaredIds, id);
                     id = stripIdPrefix(id);
                     String suggestionMessage;
@@ -229,25 +229,33 @@
                                 "The id \"%1$s\" is not defined anywhere.%2$s",
                                 id, suggestionMessage);
                     }
-                    // TODO: Compute applicable node scope
-                    context.report(UNKNOWN_ID, location, message, null);
+                    report(context, UNKNOWN_ID, handle, message);
                 } else if (checkSameLayout && (!projectScope || isBound)) {
                     // The id was defined, but in a different layout. Usually not intentional
                     // (might be referring to a random other view that happens to have the same
                     // name.)
                     Handle handle = pair.getSecond();
-                    Location location = handle.resolve();
-                    // TODO: Compute applicable node scope
-                    context.report(UNKNOWN_ID_LAYOUT, location,
+                    report(context, UNKNOWN_ID_LAYOUT, handle,
                             String.format(
                                     "The id \"%1$s\" is not referring to any views in this layout",
-                                    stripIdPrefix(id)),
-                            null);
+                                    stripIdPrefix(id)));
                 }
             }
         }
     }
 
+    private void report(Context context, Issue issue, Handle handle, String message) {
+        Location location = handle.resolve();
+        Object clientData = handle.getClientData();
+        if (clientData instanceof Attr) {
+            if (context.getDriver().isSuppressed(issue, (Attr) clientData)) {
+                return;
+            }
+        }
+
+        context.report(issue, location, message, null);
+    }
+
     @Override
     public void visitElement(XmlContext context, Element element) {
         if (element.getTagName().equals(RELATIVE_LAYOUT)) {
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/WrongIdDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/WrongIdDetectorTest.java
index 337ac5d..5783bd1 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/WrongIdDetectorTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/WrongIdDetectorTest.java
@@ -48,4 +48,23 @@
 
             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"));
+    }
+
 }
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/wrongid/ignorelayout1.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/wrongid/ignorelayout1.xml
new file mode 100644
index 0000000..deca8b3
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/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" />
+
+    <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>