Merge "Support view cookies in menus." into idea133
diff --git a/android/src/com/android/tools/idea/rendering/LayoutPsiPullParser.java b/android/src/com/android/tools/idea/rendering/LayoutPsiPullParser.java
index 36568d7..f75d0c8 100644
--- a/android/src/com/android/tools/idea/rendering/LayoutPsiPullParser.java
+++ b/android/src/com/android/tools/idea/rendering/LayoutPsiPullParser.java
@@ -19,6 +19,7 @@
 import com.android.ide.common.rendering.api.ILayoutPullParser;
 import com.android.ide.common.res2.ValueXmlHelper;
 import com.android.resources.Density;
+import com.android.resources.ResourceFolderType;
 import com.google.common.base.Splitter;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
@@ -64,7 +65,7 @@
   @Nullable
   protected String myAndroidPrefix;
 
-  private boolean myProvideViewCookies = true;
+  protected boolean myProvideViewCookies = true;
 
   /**
    * Constructs a new {@link LayoutPsiPullParser}, a parser dedicated to the special case of
@@ -75,6 +76,30 @@
    */
   @NotNull
   public static LayoutPsiPullParser create(@NotNull XmlFile file, @NotNull RenderLogger logger) {
+    if (ResourceHelper.getFolderType(file) == ResourceFolderType.MENU) {
+      return new LayoutPsiPullParser(file, logger) {
+        @Nullable
+        @Override
+        public Object getViewCookie() {
+          if (myProvideViewCookies) {
+            Element element = getCurrentNode();
+            if (element != null) {
+              // <menu> tags means that we are adding a sub-menu. Since we don't show the submenu, we
+              // return the enclosing tag.
+              if (element.tag.equals(FD_RES_MENU)) {
+                Element previousElement = getPreviousNode();
+                if (previousElement != null) {
+                  return previousElement.cookie;
+                }
+              }
+              return element.cookie;
+            }
+          }
+
+          return null;
+        }
+      };
+    }
     return new LayoutPsiPullParser(file, logger);
   }
 
@@ -183,6 +208,15 @@
   }
 
   @Nullable
+  protected final Element getPreviousNode() {
+    if (myNodeStack.size() > 1) {
+      return myNodeStack.get(myNodeStack.size() - 2);
+    }
+
+    return null;
+  }
+
+  @Nullable
   protected final Attribute getAttribute(int i) {
     if (myParsingState != START_TAG) {
       throw new IndexOutOfBoundsException();
diff --git a/android/src/com/android/tools/idea/rendering/LayoutlibCallback.java b/android/src/com/android/tools/idea/rendering/LayoutlibCallback.java
index f09f7a4..a45c105 100644
--- a/android/src/com/android/tools/idea/rendering/LayoutlibCallback.java
+++ b/android/src/com/android/tools/idea/rendering/LayoutlibCallback.java
@@ -21,7 +21,6 @@
 import com.android.ide.common.rendering.legacy.LegacyCallback;
 import com.android.ide.common.resources.ResourceResolver;
 import com.android.resources.ResourceType;
-import com.android.tools.idea.model.ManifestInfo;
 import com.android.tools.lint.detector.api.LintUtils;
 import com.android.utils.HtmlBuilder;
 import com.android.utils.SdkUtils;
@@ -76,11 +75,11 @@
   @Nullable private final Object myCredential;
   @Nullable private String myNamespace;
   @Nullable private RenderLogger myLogger;
-  @NotNull private ViewLoader myClassLoader;
+  @NotNull private final ViewLoader myClassLoader;
   @Nullable private String myLayoutName;
   @Nullable private ILayoutPullParser myLayoutEmbeddedParser;
   @Nullable private ResourceResolver myResourceResolver;
-  @NotNull private ActionBarHandler myActionBarHandler;
+  @NotNull private final ActionBarHandler myActionBarHandler;
   private boolean myUsed = false;
   private Set<File> myParserFiles;
   private int myParserCount;
@@ -269,7 +268,7 @@
   @Nullable
   @Override
   public ILayoutPullParser getParser(@NotNull ResourceValue layoutResource) {
-    return getParser(layoutResource.getName(), new File(layoutResource.getName()));
+    return getParser(layoutResource.getName(), new File(layoutResource.getValue()));
   }
 
   @Nullable
@@ -307,17 +306,22 @@
     // contents rather than the most recently saved file contents.
     if (xml != null && xml.isFile()) {
       File parent = xml.getParentFile();
-      if (parent != null && parent.getName().startsWith(FD_RES_LAYOUT)) {
-        VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(xml);
-        if (file != null) {
-          PsiManager psiManager = PsiManager.getInstance(myModule.getProject());
-          PsiFile psiFile = psiManager.findFile(file);
-          if (psiFile instanceof XmlFile) {
-            assert myLogger != null;
-            LayoutPsiPullParser parser = LayoutPsiPullParser.create((XmlFile)psiFile, myLogger);
-            // For included layouts, don't see view cookies; we want the leaf to point back to the include tag
-            parser.setProvideViewCookies(false);
-            return parser;
+      if (parent != null) {
+        String parentName = parent.getName();
+        if (parentName.startsWith(FD_RES_LAYOUT) || parentName.startsWith(FD_RES_MENU)) {
+          VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(xml);
+          if (file != null) {
+            PsiManager psiManager = PsiManager.getInstance(myModule.getProject());
+            PsiFile psiFile = psiManager.findFile(file);
+            if (psiFile instanceof XmlFile) {
+              assert myLogger != null;
+              LayoutPsiPullParser parser = LayoutPsiPullParser.create((XmlFile)psiFile, myLogger);
+              if (parentName.startsWith(FD_RES_LAYOUT)) {
+                // For included layouts, don't see view cookies; we want the leaf to point back to the include tag
+                parser.setProvideViewCookies(false);
+              }
+              return parser;
+            }
           }
         }
       }