diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java
index f9692f344727..a46ea84c3183 100644
--- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java
+++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java
@@ -62,6 +62,7 @@ import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.maven.AndroidMavenUtil;
import org.jetbrains.android.refactoring.AndroidExtractAsIncludeAction;
import org.jetbrains.android.refactoring.AndroidExtractStyleAction;
+import org.jetbrains.android.refactoring.AndroidInlineIncludeAction;
import org.jetbrains.android.refactoring.AndroidInlineStyleReferenceAction;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.sdk.AndroidSdkUtils;
@@ -171,6 +172,9 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
action = manager.getAction(AndroidExtractAsIncludeAction.ACTION_ID);
group.add(new AndroidRefactoringActionWrapper("E_xtract Layout", action));
+
+ action = manager.getAction(AndroidInlineIncludeAction.ACTION_ID);
+ group.add(new AndroidRefactoringActionWrapper("I_nline Layout", action));
return group;
}
diff --git a/plugins/android/resources/messages/AndroidBundle.properties b/plugins/android/resources/messages/AndroidBundle.properties
index 8b6f534025db..ec5dc1f84cd0 100644
--- a/plugins/android/resources/messages/AndroidBundle.properties
+++ b/plugins/android/resources/messages/AndroidBundle.properties
@@ -426,4 +426,8 @@ android.inline.style.title=Inline Android Style
android.inline.style.command.name=Inline Style ''{0}''
android.inline.style.inline.all.text=Inline &all references and remove the style
android.inline.style.inline.this.text=Inline &this usage and keep the style
-android.extract.as.include.title=Extract Android Layout
\ No newline at end of file
+android.extract.as.include.title=Extract Android Layout
+android.inline.layout.command.name=Inline Layout File ''{0}''
+android.inline.file.inline.all.text=Inline &all references and remove the file
+android.inline.file.inline.this.text=Inline &this usage and keep the file
+android.inline.layout.title=Inline Android Layout
\ No newline at end of file
diff --git a/plugins/android/src/META-INF/plugin.xml b/plugins/android/src/META-INF/plugin.xml
index 64b3c6a4c6af..5c04e274c760 100644
--- a/plugins/android/src/META-INF/plugin.xml
+++ b/plugins/android/src/META-INF/plugin.xml
@@ -94,6 +94,10 @@
text="Inline _Style..." description="Inlines Android style">
+
+
+
JUnit
@@ -247,7 +251,8 @@
-
+
+
@@ -255,4 +260,4 @@
-
+
\ No newline at end of file
diff --git a/plugins/android/src/org/jetbrains/android/dom/converters/AndroidResourceReferenceBase.java b/plugins/android/src/org/jetbrains/android/dom/converters/AndroidResourceReferenceBase.java
index 309647f84615..c433d26cc501 100644
--- a/plugins/android/src/org/jetbrains/android/dom/converters/AndroidResourceReferenceBase.java
+++ b/plugins/android/src/org/jetbrains/android/dom/converters/AndroidResourceReferenceBase.java
@@ -45,6 +45,11 @@ public class AndroidResourceReferenceBase extends PsiReferenceBase.Poly usages = new HashSet();
- addReferences(myStyleElement, usages);
+ AndroidInlineUtil.addReferences(myStyleElement, usages);
for (PsiField field : AndroidResourceUtil.findResourceFieldsForValueResource(myStyleTag, false)) {
- addReferences(field, usages);
+ AndroidInlineUtil.addReferences(field, usages);
}
return usages.toArray(new UsageInfo[usages.size()]);
}
- private static void addReferences(@NotNull PsiElement element, @NotNull Collection result) {
- for (PsiReference reference : ReferencesSearch.search(element)) {
- result.add(new UsageInfo(reference.getElement()));
- }
- }
-
@Override
protected void performRefactoring(UsageInfo[] usages) {
@@ -112,7 +98,7 @@ class AndroidInlineAllStyleUsagesProcessor extends BaseRefactoringProcessor {
continue;
}
final XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
- StyleUsageData usageData = tag != null ? AndroidInlineUtil.getUsageData(tag) : null;
+ StyleUsageData usageData = tag != null ? AndroidInlineUtil.getStyleUsageData(tag) : null;
if (usageData == null) {
if (usage.getReference() instanceof ResourceNameConverter.MyParentStyleReference) {
@@ -135,7 +121,8 @@ class AndroidInlineAllStyleUsagesProcessor extends BaseRefactoringProcessor {
unambiguousUsages.size() > 0 ||
unsupportedUsages.size() > 0 ||
implicitlyInherited.size() > 0) {
- final String errorMessage = buildErrorMessage(myProject, nonXmlUsages, unambiguousUsages, unsupportedUsages, implicitlyInherited);
+ final String errorMessage = AndroidInlineUtil
+ .buildErrorMessage(myProject, nonXmlUsages, unambiguousUsages, unsupportedUsages, implicitlyInherited);
AndroidUtils.reportError(myProject, errorMessage, AndroidBundle.message("android.inline.style.title"));
return;
}
@@ -156,88 +143,4 @@ class AndroidInlineAllStyleUsagesProcessor extends BaseRefactoringProcessor {
// do it because the refactoring can be invoked from UI designer
return UndoConfirmationPolicy.REQUEST_CONFIRMATION;
}
-
- @NotNull
- private static String buildErrorMessage(Project project,
- Collection nonXmlUsages,
- Collection unambiguousUsages,
- Collection unsupportedUsages,
- Collection implicitlyInherited) {
- final StringBuilder builder = new StringBuilder("Cannot perform refactoring\n\n");
-
- if (nonXmlUsages.size() > 0) {
- builder.append("Non-XML references are not supported:\n");
- buildString(builder, project, nonXmlUsages);
- builder.append("\n\n");
- }
-
- if (unambiguousUsages.size() > 0) {
- builder.append("Unambiguous references:\n");
- buildString(builder, project, unambiguousUsages);
- builder.append("\n\n");
- }
-
- if (unsupportedUsages.size() > 0) {
- builder.append("Unsupported references:\n");
- buildString(builder, project, unsupportedUsages);
- builder.append("\n\n");
- }
-
- if (implicitlyInherited.size() > 0) {
- builder.append("Implicit inheritance is not supported:\n");
- buildString(builder, project, implicitlyInherited);
- builder.append("\n\n");
- }
- builder.delete(builder.length() - 2, builder.length());
- return builder.toString();
- }
-
- private static void buildString(StringBuilder builder, Project project, Collection invalidRefs) {
- final OrderedSet lines = new OrderedSet();
-
- for (PsiElement usage : invalidRefs) {
- final PsiFile psiFile = usage.getContainingFile();
- final VirtualFile file = psiFile != null
- ? psiFile.getVirtualFile()
- : null;
- if (file != null) {
- lines.add(" in '" + getPresentableFilePath(project, file) + "'");
- }
- else {
- lines.add(" in unknown file");
- }
- }
-
- for (Iterator it = lines.iterator(); it.hasNext(); ) {
- final String line = it.next();
- builder.append(line);
-
- if (it.hasNext()) {
- builder.append('\n');
- }
- }
- }
-
- private static String getPresentableFilePath(Project project, VirtualFile file) {
- final ProjectRootManager projectRootManager = ProjectRootManager.getInstance(project);
- final int contentRootCount = projectRootManager.getContentRoots().length;
-
- if (contentRootCount == 0) {
- return file.getPath();
- }
- final VirtualFile contentRoot = projectRootManager.getFileIndex().getContentRootForFile(file);
-
- if (contentRoot == null) {
- return file.getPath();
- }
- final String relativePath = VfsUtilCore.getRelativePath(file, contentRoot, '/');
-
- if (relativePath == null) {
- return file.getPath();
- }
- final String presentableRelativePath = contentRootCount == 1
- ? relativePath
- : contentRoot.getName() + '/' + relativePath;
- return FileUtil.toSystemDependentName(".../" + presentableRelativePath);
- }
}
diff --git a/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineIncludeAction.java b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineIncludeAction.java
new file mode 100644
index 000000000000..96ecdd07588c
--- /dev/null
+++ b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineIncludeAction.java
@@ -0,0 +1,81 @@
+package org.jetbrains.android.refactoring;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.util.xml.DomManager;
+import org.jetbrains.android.dom.converters.AndroidResourceReferenceBase;
+import org.jetbrains.android.dom.layout.LayoutDomFileDescription;
+import org.jetbrains.android.util.AndroidBundle;
+import org.jetbrains.android.util.AndroidUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class AndroidInlineIncludeAction extends AndroidBaseXmlRefactoringAction {
+ private final AndroidInlineTestConfig myTestConfig;
+
+ public static final String ACTION_ID = "AndroidInlineIncludeAction";
+
+ @SuppressWarnings("UnusedDeclaration")
+ public AndroidInlineIncludeAction() {
+ myTestConfig = null;
+ }
+
+ @TestOnly
+ public AndroidInlineIncludeAction(AndroidInlineTestConfig testConfig) {
+ myTestConfig = testConfig;
+ }
+
+ @Override
+ protected void doRefactorForTags(@NotNull Project project, @NotNull final XmlTag[] tags) {
+ assert tags.length == 1;
+ final XmlTag tag = tags[0];
+
+ final PsiFile file = tag.getContainingFile();
+ if (file == null) {
+ return;
+ }
+ final LayoutUsageData usageData = AndroidInlineUtil.getLayoutUsageData(tag);
+
+ if (usageData == null) {
+ return;
+ }
+ final AndroidResourceReferenceBase reference = usageData.getReference();
+ final String title = AndroidBundle.message("android.inline.layout.title");
+ final PsiElement[] resolvedElements = reference.computeTargetElements();
+
+ if (resolvedElements.length == 0) {
+ AndroidUtils.reportError(project, "Cannot find layout by reference '" + reference.getValue() + "'", title);
+ return;
+ }
+
+ if (resolvedElements.length > 1) {
+ AndroidUtils.reportError(project, RefactoringBundle.getCannotRefactorMessage("Unambiguous layout reference."), title);
+ return;
+ }
+ final PsiElement resolvedElement = resolvedElements[0];
+
+ if (!(resolvedElement instanceof XmlFile)) {
+ AndroidUtils.reportError(project, "Cannot find layout by reference '" + reference.getValue() + "'", title);
+ return;
+ }
+ AndroidInlineUtil.doInlineLayoutFile(project, (XmlFile)resolvedElement, usageData.getReference().getElement(), myTestConfig);
+ }
+
+ @Override
+ protected boolean isEnabledForTags(@NotNull XmlTag[] tags) {
+ return tags.length == 1 && AndroidInlineUtil.getLayoutUsageData(tags[0]) != null;
+ }
+
+ @Override
+ protected boolean isMyFile(PsiFile file) {
+ return DomManager.getDomManager(file.getProject()).
+ getDomFileDescription((XmlFile)file) instanceof LayoutDomFileDescription;
+ }
+}
diff --git a/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineLayoutDialog.java b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineLayoutDialog.java
new file mode 100644
index 000000000000..543fdc233a9e
--- /dev/null
+++ b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineLayoutDialog.java
@@ -0,0 +1,63 @@
+package org.jetbrains.android.refactoring;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.refactoring.inline.InlineOptionsDialog;
+import org.jetbrains.android.util.AndroidBundle;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class AndroidInlineLayoutDialog extends InlineOptionsDialog {
+ private final XmlFile myLayoutFile;
+ private final XmlTag myLayoutRootTag;
+ private final PsiElement myUsageElement;
+
+ public AndroidInlineLayoutDialog(@NotNull Project project,
+ @NotNull XmlFile layoutFile,
+ @NotNull XmlTag layoutRootTag,
+ @Nullable PsiElement usageElement) {
+ super(project, true, layoutFile);
+ myLayoutFile = layoutFile;
+ myLayoutRootTag = layoutRootTag;
+ myUsageElement = usageElement;
+ myInvokedOnReference = usageElement != null;
+ setTitle(AndroidBundle.message("android.inline.layout.title"));
+ init();
+ }
+
+ @Override
+ protected String getNameLabelText() {
+ return "Layout file '" + myLayoutFile.getName() + "'";
+ }
+
+ @Override
+ protected String getBorderTitle() {
+ return "Inline";
+ }
+
+ @Override
+ protected String getInlineAllText() {
+ return AndroidBundle.message("android.inline.file.inline.all.text");
+ }
+
+ @Override
+ protected String getInlineThisText() {
+ return AndroidBundle.message("android.inline.file.inline.this.text");
+ }
+
+ @Override
+ protected boolean isInlineThis() {
+ return myUsageElement != null;
+ }
+
+ @Override
+ protected void doAction() {
+ final PsiElement usageElement = isInlineThisOnly() ? myUsageElement : null;
+ invokeRefactoring(new AndroidInlineLayoutProcessor(myProject, myLayoutFile, myLayoutRootTag, usageElement));
+ }
+}
diff --git a/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineLayoutHandler.java b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineLayoutHandler.java
new file mode 100644
index 000000000000..ba13e20f52cf
--- /dev/null
+++ b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineLayoutHandler.java
@@ -0,0 +1,122 @@
+package org.jetbrains.android.refactoring;
+
+import com.intellij.codeInsight.TargetElementUtilBase;
+import com.intellij.lang.Language;
+import com.intellij.lang.refactoring.InlineActionHandler;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.xml.DomManager;
+import org.jetbrains.android.dom.converters.AndroidResourceReferenceBase;
+import org.jetbrains.android.dom.layout.LayoutDomFileDescription;
+import org.jetbrains.android.dom.wrappers.ResourceElementWrapper;
+import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.android.util.AndroidBundle;
+import org.jetbrains.android.util.ErrorReporter;
+import org.jetbrains.android.util.HintBasedErrorReporter;
+import org.jetbrains.android.util.ProjectBasedErrorReporter;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class AndroidInlineLayoutHandler extends InlineActionHandler {
+ private static AndroidInlineTestConfig ourTestConfig;
+
+ @TestOnly
+ public static void setTestConfig(@Nullable AndroidInlineTestConfig testConfig) {
+ ourTestConfig = testConfig;
+ }
+
+ @Override
+ public boolean isEnabledForLanguage(Language l) {
+ return l == XMLLanguage.INSTANCE;
+ }
+
+ @Override
+ public boolean canInlineElement(PsiElement element) {
+ if (element instanceof ResourceElementWrapper) {
+ element = ((ResourceElementWrapper)element).getWrappee();
+ }
+ if (!(element instanceof XmlElement)) {
+ return false;
+ }
+ if (AndroidFacet.getInstance(element) == null) {
+ return false;
+ }
+ if (element instanceof XmlFile) {
+ if (((XmlFile)element).getRootTag() == null) {
+ return false;
+ }
+ return DomManager.getDomManager(element.getProject()).getDomFileDescription((XmlFile)element)
+ instanceof LayoutDomFileDescription;
+ }
+ else if (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_NAME) {
+ return getLayoutUsageDataFromContext(element) != null;
+ }
+ return false;
+ }
+
+ @Nullable
+ private static LayoutUsageData getLayoutUsageDataFromContext(PsiElement context) {
+ final XmlTag tag = PsiTreeUtil.getParentOfType(context, XmlTag.class);
+ return tag != null
+ ? AndroidInlineUtil.getLayoutUsageData(tag)
+ : null;
+ }
+
+ @Override
+ public void inlineElement(Project project, Editor editor, PsiElement element) {
+ if (element instanceof ResourceElementWrapper) {
+ element = ((ResourceElementWrapper)element).getWrappee();
+ }
+
+ if (element instanceof XmlFile) {
+ PsiElement usageElement = null;
+
+ if (editor != null) {
+ final PsiReference reference = TargetElementUtilBase.findReference(editor);
+
+ if (reference != null) {
+ usageElement = reference.getElement();
+ }
+ }
+ AndroidInlineUtil.doInlineLayoutFile(project, (XmlFile)element, usageElement, ourTestConfig);
+ return;
+ }
+ final LayoutUsageData usageData = getLayoutUsageDataFromContext(element);
+ assert usageData != null;
+ final AndroidResourceReferenceBase ref = usageData.getReference();
+ final PsiElement[] elements = ref.computeTargetElements();
+ final ErrorReporter errorReporter = editor != null
+ ? new HintBasedErrorReporter(editor)
+ : new ProjectBasedErrorReporter(project);
+ final String title = AndroidBundle.message("android.inline.layout.title");
+
+ if (elements.length == 0) {
+ final String resName = ref.getResourceValue().getResourceName();
+ final String message = resName != null
+ ? "Cannot find layout '" + resName + "'"
+ : "Error: cannot find the layout";
+ errorReporter.report(message, title);
+ return;
+ }
+
+ if (elements.length > 1) {
+ errorReporter.report("Error: unambiguous reference", title);
+ return;
+ }
+
+ final PsiElement resolvedElement = elements[0];
+ if (!(resolvedElement instanceof XmlFile)) {
+ errorReporter.report("Cannot inline reference '" + ref.getValue() + "'", title);
+ return;
+ }
+ AndroidInlineUtil.doInlineLayoutFile(project, (XmlFile)resolvedElement, usageData.getIncludeTag(), ourTestConfig);
+ }
+}
diff --git a/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineLayoutProcessor.java b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineLayoutProcessor.java
new file mode 100644
index 000000000000..582fc9b6ca45
--- /dev/null
+++ b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineLayoutProcessor.java
@@ -0,0 +1,155 @@
+package org.jetbrains.android.refactoring;
+
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.command.UndoConfirmationPolicy;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiField;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.refactoring.BaseRefactoringProcessor;
+import com.intellij.refactoring.ui.UsageViewDescriptorAdapter;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.usageView.UsageViewBundle;
+import com.intellij.usageView.UsageViewDescriptor;
+import com.intellij.util.containers.HashSet;
+import org.jetbrains.android.util.AndroidBundle;
+import org.jetbrains.android.util.AndroidResourceUtil;
+import org.jetbrains.android.util.AndroidUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class AndroidInlineLayoutProcessor extends BaseRefactoringProcessor {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.refactoring.AndroidInlineLayoutProcessor");
+
+ private final XmlFile myLayoutFile;
+ private final XmlTag myLayoutRootTag;
+ private final PsiElement myUsageElement;
+
+ protected AndroidInlineLayoutProcessor(@NotNull Project project,
+ @NotNull XmlFile file,
+ @NotNull XmlTag rootTag,
+ @Nullable PsiElement usageElement) {
+ super(project);
+ myLayoutFile = file;
+ myLayoutRootTag = rootTag;
+ myUsageElement = usageElement;
+ }
+
+ @NotNull
+ @Override
+ protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) {
+ return new UsageViewDescriptorAdapter() {
+ @NotNull
+ @Override
+ public PsiElement[] getElements() {
+ return new PsiElement[]{myLayoutFile};
+ }
+
+ @Override
+ public String getCodeReferencesText(int usagesCount, int filesCount) {
+ return "References to be inlined" + UsageViewBundle.getReferencesString(usagesCount, filesCount);
+ }
+
+ @Override
+ public String getProcessedElementsHeader() {
+ return "Layout file to inline";
+ }
+ };
+ }
+
+ @NotNull
+ @Override
+ protected UsageInfo[] findUsages() {
+ if (myUsageElement != null) {
+ return new UsageInfo[] {new UsageInfo(myUsageElement)};
+ }
+ final Set usages = new HashSet();
+ AndroidInlineUtil.addReferences(myLayoutFile, usages);
+
+ for (PsiField field : AndroidResourceUtil.findResourceFieldsForFileResource(myLayoutFile, false)) {
+ AndroidInlineUtil.addReferences(field, usages);
+ }
+ return usages.toArray(new UsageInfo[usages.size()]);
+ }
+
+ @Override
+ protected void performRefactoring(UsageInfo[] usages) {
+ final List inlineInfos = new ArrayList();
+ final List nonXmlUsages = new ArrayList();
+ final List unsupportedUsages = new ArrayList();
+ final List unambiguousUsages = new ArrayList();
+
+ for (UsageInfo usage : usages) {
+ final PsiElement element = usage.getElement();
+ if (element == null) continue;
+
+ if (element.getLanguage() != XMLLanguage.INSTANCE) {
+ nonXmlUsages.add(element);
+ continue;
+ }
+ final XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
+ final LayoutUsageData usageData = tag != null
+ ? AndroidInlineUtil.getLayoutUsageData(tag)
+ : null;
+ if (usageData == null) {
+ unsupportedUsages.add(element);
+ continue;
+ }
+
+ if (usageData.getReference().computeTargetElements().length > 1) {
+ unambiguousUsages.add(element);
+ continue;
+ }
+ inlineInfos.add(usageData);
+ }
+
+ if (nonXmlUsages.size() > 0 || unambiguousUsages.size() > 0 || unsupportedUsages.size() > 0) {
+ final String errorMessage = AndroidInlineUtil.buildErrorMessage(
+ myProject, nonXmlUsages, unambiguousUsages, unsupportedUsages,
+ Collections.emptyList());
+ AndroidUtils.reportError(myProject, errorMessage, AndroidBundle.message("android.inline.style.title"));
+ return;
+ }
+
+ for (LayoutUsageData info : inlineInfos) {
+ try {
+ info.inline(myLayoutRootTag);
+ }
+ catch (AndroidRefactoringErrorException e) {
+ LOG.info(e);
+ String message = e.getMessage();
+
+ if (message == null) {
+ message = "Refactoring was performed with errors";
+ }
+ AndroidUtils.reportError(myProject, message, AndroidBundle.message("android.inline.style.title"));
+ return;
+ }
+ }
+ if (myUsageElement == null) {
+ myLayoutFile.delete();
+ }
+ }
+
+ @Override
+ protected String getCommandName() {
+ return AndroidBundle.message("android.inline.layout.command.name", myLayoutFile.getName());
+ }
+
+ @Override
+ protected UndoConfirmationPolicy getUndoConfirmationPolicy() {
+ // do it because the refactoring can be invoked from UI designer
+ return UndoConfirmationPolicy.REQUEST_CONFIRMATION;
+ }
+}
diff --git a/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineStyleHandler.java b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineStyleHandler.java
index 198d9afa087a..866e65c6c37b 100644
--- a/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineStyleHandler.java
+++ b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineStyleHandler.java
@@ -76,6 +76,6 @@ public class AndroidInlineStyleHandler extends InlineActionHandler {
return null;
}
final XmlTag tag = PsiTreeUtil.getParentOfType(usageElement, XmlTag.class, false);
- return tag != null ? AndroidInlineUtil.getUsageData(tag) : null;
+ return tag != null ? AndroidInlineUtil.getStyleUsageData(tag) : null;
}
}
diff --git a/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineStyleReferenceAction.java b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineStyleReferenceAction.java
index 5a69d1965029..363e8322ffc7 100644
--- a/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineStyleReferenceAction.java
+++ b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineStyleReferenceAction.java
@@ -47,7 +47,7 @@ public class AndroidInlineStyleReferenceAction extends AndroidBaseXmlRefactoring
if (file == null) {
return;
}
- final StyleUsageData usageData = AndroidInlineUtil.getUsageData(tag);
+ final StyleUsageData usageData = AndroidInlineUtil.getStyleUsageData(tag);
if (usageData == null) {
return;
@@ -87,7 +87,7 @@ public class AndroidInlineStyleReferenceAction extends AndroidBaseXmlRefactoring
@Override
protected boolean isEnabledForTags(@NotNull XmlTag[] tags) {
- return tags.length == 1 && AndroidInlineUtil.getUsageData(tags[0]) != null;
+ return tags.length == 1 && AndroidInlineUtil.getStyleUsageData(tags[0]) != null;
}
@Override
diff --git a/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineUtil.java b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineUtil.java
index 3c94d0cb27e2..9d43e8588a2c 100644
--- a/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineUtil.java
+++ b/plugins/android/src/org/jetbrains/android/refactoring/AndroidInlineUtil.java
@@ -5,18 +5,27 @@ import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
+import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.usageView.UsageInfo;
import com.intellij.util.containers.HashMap;
+import com.intellij.util.containers.OrderedSet;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomManager;
import com.intellij.util.xml.GenericAttributeValue;
import org.jetbrains.android.dom.converters.AndroidResourceReferenceBase;
+import org.jetbrains.android.dom.layout.Include;
import org.jetbrains.android.dom.layout.LayoutViewElement;
import org.jetbrains.android.dom.resources.ResourceValue;
import org.jetbrains.android.dom.resources.Style;
@@ -28,6 +37,8 @@ import org.jetbrains.android.util.ErrorReporter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.Map;
/**
@@ -59,7 +70,7 @@ class AndroidInlineUtil {
}
@Nullable
- static StyleUsageData getUsageData(@NotNull XmlTag tag) {
+ static StyleUsageData getStyleUsageData(@NotNull XmlTag tag) {
final DomElement domElement = DomManager.getDomManager(tag.getProject()).getDomElement(tag);
if (domElement instanceof LayoutViewElement) {
@@ -80,23 +91,39 @@ class AndroidInlineUtil {
return null;
}
+ @Nullable
+ static LayoutUsageData getLayoutUsageData(@NotNull XmlTag tag) {
+ final Project project = tag.getProject();
+ final DomElement domElement = DomManager.getDomManager(project).getDomElement(tag);
+
+ if (domElement instanceof Include) {
+ final GenericAttributeValue layoutAttribute = ((Include)domElement).getLayout();
+ final AndroidResourceReferenceBase reference = getAndroidResourceReference(layoutAttribute);
+
+ if (reference != null) {
+ return new LayoutUsageData(project, tag, reference);
+ }
+ }
+ return null;
+ }
+
@Nullable
private static AndroidResourceReferenceBase getAndroidResourceReference(@Nullable GenericAttributeValue attribute) {
if (attribute == null) {
return null;
}
- final ResourceValue styleValue = attribute.getValue();
- if (styleValue == null || styleValue.getPackage() != null) {
+ final ResourceValue resValue = attribute.getValue();
+ if (resValue == null || resValue.getPackage() != null) {
return null;
}
- final XmlAttributeValue styleAttributeValue = attribute.getXmlAttributeValue();
- if (styleAttributeValue == null) {
+ final XmlAttributeValue value = attribute.getXmlAttributeValue();
+ if (value == null) {
return null;
}
- for (PsiReference reference : styleAttributeValue.getReferences()) {
+ for (PsiReference reference : value.getReferences()) {
if (reference instanceof AndroidResourceReferenceBase) {
return (AndroidResourceReferenceBase)reference;
}
@@ -237,6 +264,115 @@ class AndroidInlineUtil {
? data : null;
}
+ static void addReferences(@NotNull PsiElement element, @NotNull Collection result) {
+ for (PsiReference reference : ReferencesSearch.search(element)) {
+ result.add(new UsageInfo(reference.getElement()));
+ }
+ }
+
+ @NotNull
+ static String buildErrorMessage(Project project,
+ Collection nonXmlUsages,
+ Collection unambiguousUsages,
+ Collection unsupportedUsages,
+ Collection implicitlyInherited) {
+ final StringBuilder builder = new StringBuilder("Cannot perform refactoring\n\n");
+
+ if (nonXmlUsages.size() > 0) {
+ builder.append("Non-XML references are not supported:\n");
+ buildString(builder, project, nonXmlUsages);
+ builder.append("\n\n");
+ }
+
+ if (unambiguousUsages.size() > 0) {
+ builder.append("Unambiguous references:\n");
+ buildString(builder, project, unambiguousUsages);
+ builder.append("\n\n");
+ }
+
+ if (unsupportedUsages.size() > 0) {
+ builder.append("Unsupported references:\n");
+ buildString(builder, project, unsupportedUsages);
+ builder.append("\n\n");
+ }
+
+ if (implicitlyInherited.size() > 0) {
+ builder.append("Implicit inheritance is not supported:\n");
+ buildString(builder, project, implicitlyInherited);
+ builder.append("\n\n");
+ }
+ builder.delete(builder.length() - 2, builder.length());
+ return builder.toString();
+ }
+
+ private static void buildString(StringBuilder builder, Project project, Collection invalidRefs) {
+ final OrderedSet lines = new OrderedSet();
+
+ for (PsiElement usage : invalidRefs) {
+ final PsiFile psiFile = usage.getContainingFile();
+ final VirtualFile file = psiFile != null
+ ? psiFile.getVirtualFile()
+ : null;
+ if (file != null) {
+ lines.add(" in '" + getPresentableFilePath(project, file) + "'");
+ }
+ else {
+ lines.add(" in unknown file");
+ }
+ }
+
+ for (Iterator it = lines.iterator(); it.hasNext(); ) {
+ final String line = it.next();
+ builder.append(line);
+
+ if (it.hasNext()) {
+ builder.append('\n');
+ }
+ }
+ }
+
+ private static String getPresentableFilePath(Project project, VirtualFile file) {
+ final ProjectRootManager projectRootManager = ProjectRootManager.getInstance(project);
+ final int contentRootCount = projectRootManager.getContentRoots().length;
+
+ if (contentRootCount == 0) {
+ return file.getPath();
+ }
+ final VirtualFile contentRoot = projectRootManager.getFileIndex().getContentRootForFile(file);
+
+ if (contentRoot == null) {
+ return file.getPath();
+ }
+ final String relativePath = VfsUtilCore.getRelativePath(file, contentRoot, '/');
+
+ if (relativePath == null) {
+ return file.getPath();
+ }
+ final String presentableRelativePath = contentRootCount == 1
+ ? relativePath
+ : contentRoot.getName() + '/' + relativePath;
+ return FileUtil.toSystemDependentName(".../" + presentableRelativePath);
+ }
+
+ static void doInlineLayoutFile(@NotNull Project project,
+ @NotNull XmlFile layoutFile,
+ @Nullable PsiElement usageElement,
+ @Nullable AndroidInlineTestConfig testConfig) {
+ final XmlTag rootTag = layoutFile.getRootTag();
+ assert rootTag != null;
+
+ if (testConfig == null) {
+ final AndroidInlineLayoutDialog dialog = new AndroidInlineLayoutDialog(project, layoutFile, rootTag, usageElement);
+ dialog.show();
+ }
+ else {
+ final AndroidInlineLayoutProcessor processor =
+ new AndroidInlineLayoutProcessor(project, layoutFile, rootTag, testConfig.isInlineThisOnly() ? usageElement : null);
+ processor.setPreviewUsages(false);
+ processor.run();
+ }
+ }
+
static class MyStyleData {
private final String myStyleName;
private final Style myStyleElement;
diff --git a/plugins/android/src/org/jetbrains/android/refactoring/AndroidRefactoringErrorException.java b/plugins/android/src/org/jetbrains/android/refactoring/AndroidRefactoringErrorException.java
new file mode 100644
index 000000000000..1cb5f4cb9e99
--- /dev/null
+++ b/plugins/android/src/org/jetbrains/android/refactoring/AndroidRefactoringErrorException.java
@@ -0,0 +1,13 @@
+package org.jetbrains.android.refactoring;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class AndroidRefactoringErrorException extends Exception {
+ public AndroidRefactoringErrorException() {
+ }
+
+ public AndroidRefactoringErrorException(String message) {
+ super(message);
+ }
+}
diff --git a/plugins/android/src/org/jetbrains/android/refactoring/LayoutUsageData.java b/plugins/android/src/org/jetbrains/android/refactoring/LayoutUsageData.java
new file mode 100644
index 000000000000..520fd62a1d24
--- /dev/null
+++ b/plugins/android/src/org/jetbrains/android/refactoring/LayoutUsageData.java
@@ -0,0 +1,200 @@
+package org.jetbrains.android.refactoring;
+
+import com.android.sdklib.SdkConstants;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.XmlElementFactory;
+import com.intellij.psi.codeStyle.CodeStyleManager;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.containers.HashMap;
+import org.jetbrains.android.dom.converters.AndroidResourceReferenceBase;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class LayoutUsageData {
+ private final Project myProject;
+ private final XmlTag myIncludeTag;
+ private final AndroidResourceReferenceBase myReference;
+
+ public LayoutUsageData(@NotNull Project project,
+ @NotNull XmlTag includeTag,
+ @NotNull AndroidResourceReferenceBase reference) {
+ myProject = project;
+ myIncludeTag = includeTag;
+ myReference = reference;
+ }
+
+ @NotNull
+ public AndroidResourceReferenceBase getReference() {
+ return myReference;
+ }
+
+ public void inline(@NotNull XmlTag layoutRootTag) throws AndroidRefactoringErrorException {
+ final XmlTag parent = myIncludeTag.getParentTag();
+
+ if ("merge".equals(layoutRootTag.getName()) && parent != null) {
+ inlineMultiTags(myIncludeTag, parent, layoutRootTag, myProject);
+ }
+ else {
+ inlineSingleTag(myIncludeTag, parent, layoutRootTag);
+ }
+ }
+
+ @NotNull
+ public XmlTag getIncludeTag() {
+ return myIncludeTag;
+ }
+
+ private static void inlineSingleTag(XmlTag includeTag, XmlTag includeParentTag, XmlTag layoutRootTag) {
+ final Map attributesToAdd = new HashMap();
+
+ for (XmlAttribute attribute : includeTag.getAttributes()) {
+ final String namespace = attribute.getNamespace();
+
+ if (SdkConstants.NS_RESOURCES.equals(namespace)) {
+ attributesToAdd.put(attribute.getLocalName(), attribute.getValue());
+ }
+ }
+ final XmlTag newTag = (XmlTag)includeTag.replace(layoutRootTag.copy());
+ final List toDelete = new ArrayList();
+
+ for (XmlAttribute attribute : newTag.getAttributes()) {
+ if (attribute.isNamespaceDeclaration()) {
+ final String localName = attribute.getLocalName();
+ final String prefix = localName.equals(attribute.getName()) ? "" : localName;
+ final String namespace = attribute.getValue();
+
+ if (includeParentTag != null && namespace.equals(includeParentTag.getNamespaceByPrefix(prefix))) {
+ toDelete.add(attribute);
+ }
+ }
+ }
+
+ for (XmlAttribute attribute : toDelete) {
+ attribute.delete();
+ }
+
+ for (Map.Entry entry : attributesToAdd.entrySet()) {
+ final String localName = entry.getKey();
+ final String value = entry.getValue();
+ newTag.setAttribute(localName, SdkConstants.NS_RESOURCES, value);
+ }
+ CodeStyleManager.getInstance(newTag.getManager()).reformat(newTag);
+ }
+
+ private static void inlineMultiTags(XmlTag includeTag, XmlTag includeTagParent, XmlTag mergeTag, Project project)
+ throws AndroidRefactoringErrorException {
+ final Map namespacesFromParent = includeTagParent.getLocalNamespaceDeclarations();
+ final Map namespacesToAddToParent = new HashMap();
+ final Map namespacesToAddToEachTag = new HashMap();
+
+ for (Map.Entry entry : mergeTag.getLocalNamespaceDeclarations().entrySet()) {
+ final String prefix = entry.getKey();
+ final String namespace = entry.getValue();
+ final String declaredNamespace = namespacesFromParent.get(prefix);
+
+ if (declaredNamespace != null && !declaredNamespace.equals(namespace)) {
+ namespacesToAddToEachTag.put(prefix, namespace);
+ }
+ else {
+ namespacesToAddToParent.put(prefix, namespace);
+ }
+ }
+ final XmlTag mergeTagCopy = (XmlTag)mergeTag.copy();
+ final XmlElementFactory xmlElementFactory = XmlElementFactory.getInstance(project);
+
+ for (XmlTag subtag : mergeTagCopy.getSubTags()) {
+ final XmlAttribute[] attributes = subtag.getAttributes();
+ final XmlAttribute firstAttribute = attributes.length > 0 ? attributes[0] : null;
+
+ for (Map.Entry entry : namespacesToAddToEachTag.entrySet()) {
+ final String prefix = entry.getKey();
+ final String namespace = entry.getValue();
+
+ if (!subtag.getLocalNamespaceDeclarations().containsKey(prefix)) {
+ final XmlAttribute xmlnsAttr = xmlElementFactory.createXmlAttribute("xmlns:" + prefix, namespace);
+
+ if (firstAttribute != null) {
+ subtag.addBefore(xmlnsAttr, firstAttribute);
+ }
+ else {
+ subtag.add(xmlnsAttr);
+ }
+ }
+ }
+ }
+ replaceByTagContent(project, includeTag, mergeTagCopy);
+ addNamespaceAttributes(includeTagParent, namespacesToAddToParent, project);
+ }
+
+ private static void addNamespaceAttributes(XmlTag tag, Map namespaces, Project project) {
+ final XmlAttribute[] parentAttributes = tag.getAttributes();
+ final XmlAttribute firstParentAttribute = parentAttributes.length > 0 ? parentAttributes[0] : null;
+ final XmlElementFactory factory = XmlElementFactory.getInstance(project);
+
+ for (Map.Entry entry : namespaces.entrySet()) {
+ final String prefix = entry.getKey();
+ final String namespace = entry.getValue();
+
+ if (!namespace.equals(tag.getNamespaceByPrefix(prefix))) {
+ final XmlAttribute xmlnsAttr = factory.createXmlAttribute("xmlns:" + prefix, namespace);
+
+ if (firstParentAttribute != null) {
+ tag.addBefore(xmlnsAttr, firstParentAttribute);
+ }
+ else {
+ tag.add(xmlnsAttr);
+ }
+ }
+ }
+ }
+
+ private static void replaceByTagContent(Project project, XmlTag tagToReplace, XmlTag tagToInline)
+ throws AndroidRefactoringErrorException {
+ final ASTNode node = tagToInline.getNode();
+
+ if (node == null) {
+ throw new AndroidRefactoringErrorException();
+ }
+ final ASTNode startTagEnd = XmlChildRole.START_TAG_END_FINDER.findChild(node);
+ final ASTNode closingTagStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(node);
+
+ if (startTagEnd == null || closingTagStart == null) {
+ throw new AndroidRefactoringErrorException();
+ }
+ final int contentStart = startTagEnd.getTextRange().getEndOffset();
+ final int contentEnd = closingTagStart.getTextRange().getStartOffset();
+
+ if (contentStart < 0 || contentEnd < 0 || contentStart >= contentEnd) {
+ throw new AndroidRefactoringErrorException();
+ }
+ final PsiFile file = tagToInline.getContainingFile();
+
+ if(file == null) {
+ throw new AndroidRefactoringErrorException();
+ }
+ final String textToInline = file.getText().
+ substring(contentStart, contentEnd).trim();
+ final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
+ final Document document = documentManager.getDocument(tagToReplace.getContainingFile());
+
+ if (document == null) {
+ throw new AndroidRefactoringErrorException();
+ }
+ final TextRange range = tagToReplace.getTextRange();
+ document.replaceString(range.getStartOffset(), range.getEndOffset(), textToInline);
+ documentManager.commitDocument(document);
+ }
+}
diff --git a/plugins/android/testData/refactoring/inlineLayout/1.xml b/plugins/android/testData/refactoring/inlineLayout/1.xml
new file mode 100644
index 000000000000..432fb78b96cc
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/1.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/10.xml b/plugins/android/testData/refactoring/inlineLayout/10.xml
new file mode 100644
index 000000000000..432fb78b96cc
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/10.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/10_after.xml b/plugins/android/testData/refactoring/inlineLayout/10_after.xml
new file mode 100644
index 000000000000..3c39c3a7b1e9
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/10_after.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/10_included.xml b/plugins/android/testData/refactoring/inlineLayout/10_included.xml
new file mode 100644
index 000000000000..a0b0b89a54dc
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/10_included.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/11.xml b/plugins/android/testData/refactoring/inlineLayout/11.xml
new file mode 100644
index 000000000000..27d2a7cf8075
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/11.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/11_after.xml b/plugins/android/testData/refactoring/inlineLayout/11_after.xml
new file mode 100644
index 000000000000..533bfb3edb22
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/11_after.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/11_included.xml b/plugins/android/testData/refactoring/inlineLayout/11_included.xml
new file mode 100644
index 000000000000..a0b0b89a54dc
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/11_included.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/12.xml b/plugins/android/testData/refactoring/inlineLayout/12.xml
new file mode 100644
index 000000000000..460a641a9dab
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/12.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/12_after.xml b/plugins/android/testData/refactoring/inlineLayout/12_after.xml
new file mode 100644
index 000000000000..717a237560a2
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/12_after.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/12_included.xml b/plugins/android/testData/refactoring/inlineLayout/12_included.xml
new file mode 100644
index 000000000000..a0b0b89a54dc
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/12_included.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/13.xml b/plugins/android/testData/refactoring/inlineLayout/13.xml
new file mode 100644
index 000000000000..f66fb8a50468
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/13.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/13_after.xml b/plugins/android/testData/refactoring/inlineLayout/13_after.xml
new file mode 100644
index 000000000000..cfef7670cc56
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/13_after.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/13_included.xml b/plugins/android/testData/refactoring/inlineLayout/13_included.xml
new file mode 100644
index 000000000000..a0b0b89a54dc
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/13_included.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/14.xml b/plugins/android/testData/refactoring/inlineLayout/14.xml
new file mode 100644
index 000000000000..00521b8785fa
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/14.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/14_after.xml b/plugins/android/testData/refactoring/inlineLayout/14_after.xml
new file mode 100644
index 000000000000..0b8ffbeec7ed
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/14_after.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/14_included.xml b/plugins/android/testData/refactoring/inlineLayout/14_included.xml
new file mode 100644
index 000000000000..a0b0b89a54dc
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/14_included.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/15.xml b/plugins/android/testData/refactoring/inlineLayout/15.xml
new file mode 100644
index 000000000000..130ff600280a
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/15.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/15_included.xml b/plugins/android/testData/refactoring/inlineLayout/15_included.xml
new file mode 100644
index 000000000000..64bc7d040fa4
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/15_included.xml
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/16.xml b/plugins/android/testData/refactoring/inlineLayout/16.xml
new file mode 100644
index 000000000000..130ff600280a
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/16.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/16_included.xml b/plugins/android/testData/refactoring/inlineLayout/16_included.xml
new file mode 100644
index 000000000000..64bc7d040fa4
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/16_included.xml
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/17.xml b/plugins/android/testData/refactoring/inlineLayout/17.xml
new file mode 100644
index 000000000000..73cc1905c349
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/17.xml
@@ -0,0 +1,7 @@
+
+
+ nclude layout="@layout/included"/>
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/17_after.xml b/plugins/android/testData/refactoring/inlineLayout/17_after.xml
new file mode 100644
index 000000000000..4f1e2160c5fd
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/17_after.xml
@@ -0,0 +1,11 @@
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/17_included.xml b/plugins/android/testData/refactoring/inlineLayout/17_included.xml
new file mode 100644
index 000000000000..fba76aca4891
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/17_included.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/18.xml b/plugins/android/testData/refactoring/inlineLayout/18.xml
new file mode 100644
index 000000000000..b1b42eb09834
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/18.xml
@@ -0,0 +1,8 @@
+
+
+ nclude layout="@layout/included"/>
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/18_after.xml b/plugins/android/testData/refactoring/inlineLayout/18_after.xml
new file mode 100644
index 000000000000..b8e654710d15
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/18_after.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/18_included.xml b/plugins/android/testData/refactoring/inlineLayout/18_included.xml
new file mode 100644
index 000000000000..fba76aca4891
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/18_included.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/19.xml b/plugins/android/testData/refactoring/inlineLayout/19.xml
new file mode 100644
index 000000000000..82ad3f2a1c27
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/19.xml
@@ -0,0 +1,8 @@
+
+
+
+ xtView/>
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/19_included.xml b/plugins/android/testData/refactoring/inlineLayout/19_included.xml
new file mode 100644
index 000000000000..fba76aca4891
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/19_included.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/1_after.xml b/plugins/android/testData/refactoring/inlineLayout/1_after.xml
new file mode 100644
index 000000000000..d97195a5cf8e
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/1_after.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/1_included.xml b/plugins/android/testData/refactoring/inlineLayout/1_included.xml
new file mode 100644
index 000000000000..fba76aca4891
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/1_included.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/2.xml b/plugins/android/testData/refactoring/inlineLayout/2.xml
new file mode 100644
index 000000000000..432fb78b96cc
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/2.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/20.xml b/plugins/android/testData/refactoring/inlineLayout/20.xml
new file mode 100644
index 000000000000..cee084174407
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/20.xml
@@ -0,0 +1,7 @@
+
+
+ lude layout="@layout/unknown"/>
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/20_included.xml b/plugins/android/testData/refactoring/inlineLayout/20_included.xml
new file mode 100644
index 000000000000..fba76aca4891
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/20_included.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/2_after.xml b/plugins/android/testData/refactoring/inlineLayout/2_after.xml
new file mode 100644
index 000000000000..017fdc571efb
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/2_after.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/2_included.xml b/plugins/android/testData/refactoring/inlineLayout/2_included.xml
new file mode 100644
index 000000000000..8199c040c69c
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/2_included.xml
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/3.xml b/plugins/android/testData/refactoring/inlineLayout/3.xml
new file mode 100644
index 000000000000..432fb78b96cc
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/3.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/3_after.xml b/plugins/android/testData/refactoring/inlineLayout/3_after.xml
new file mode 100644
index 000000000000..4f13ce2113ba
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/3_after.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/3_included.xml b/plugins/android/testData/refactoring/inlineLayout/3_included.xml
new file mode 100644
index 000000000000..1bc01f0be6ab
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/3_included.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/4.xml b/plugins/android/testData/refactoring/inlineLayout/4.xml
new file mode 100644
index 000000000000..432fb78b96cc
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/4.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/4_after.xml b/plugins/android/testData/refactoring/inlineLayout/4_after.xml
new file mode 100644
index 000000000000..1fdd46f71e4a
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/4_after.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/4_included.xml b/plugins/android/testData/refactoring/inlineLayout/4_included.xml
new file mode 100644
index 000000000000..a9c7f1f55d2f
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/4_included.xml
@@ -0,0 +1,8 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/5.xml b/plugins/android/testData/refactoring/inlineLayout/5.xml
new file mode 100644
index 000000000000..432fb78b96cc
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/5.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/5_after.xml b/plugins/android/testData/refactoring/inlineLayout/5_after.xml
new file mode 100644
index 000000000000..d57a17976619
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/5_after.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/5_included.xml b/plugins/android/testData/refactoring/inlineLayout/5_included.xml
new file mode 100644
index 000000000000..d1aa7763e450
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/5_included.xml
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/6.xml b/plugins/android/testData/refactoring/inlineLayout/6.xml
new file mode 100644
index 000000000000..d772acd34a5b
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/6.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/6_after.xml b/plugins/android/testData/refactoring/inlineLayout/6_after.xml
new file mode 100644
index 000000000000..f2fa163390f3
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/6_after.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/6_included.xml b/plugins/android/testData/refactoring/inlineLayout/6_included.xml
new file mode 100644
index 000000000000..a9c7f1f55d2f
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/6_included.xml
@@ -0,0 +1,8 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/7.xml b/plugins/android/testData/refactoring/inlineLayout/7.xml
new file mode 100644
index 000000000000..b38cca09d5a9
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/7.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/7_after.xml b/plugins/android/testData/refactoring/inlineLayout/7_after.xml
new file mode 100644
index 000000000000..d329c61ee793
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/7_after.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/7_included.xml b/plugins/android/testData/refactoring/inlineLayout/7_included.xml
new file mode 100644
index 000000000000..d1aa7763e450
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/7_included.xml
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/8.xml b/plugins/android/testData/refactoring/inlineLayout/8.xml
new file mode 100644
index 000000000000..432fb78b96cc
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/8.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/8_after.xml b/plugins/android/testData/refactoring/inlineLayout/8_after.xml
new file mode 100644
index 000000000000..4585f28858b7
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/8_after.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/8_included.xml b/plugins/android/testData/refactoring/inlineLayout/8_included.xml
new file mode 100644
index 000000000000..fba76aca4891
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/8_included.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/9.xml b/plugins/android/testData/refactoring/inlineLayout/9.xml
new file mode 100644
index 000000000000..a6ddd4eb44d2
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/9.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/9_after.xml b/plugins/android/testData/refactoring/inlineLayout/9_after.xml
new file mode 100644
index 000000000000..4585f28858b7
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/9_after.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/9_included.xml b/plugins/android/testData/refactoring/inlineLayout/9_included.xml
new file mode 100644
index 000000000000..c3233a50d44f
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/9_included.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/plugins/android/testData/refactoring/inlineLayout/MyActivity.java b/plugins/android/testData/refactoring/inlineLayout/MyActivity.java
new file mode 100644
index 000000000000..5c53b74d2cdf
--- /dev/null
+++ b/plugins/android/testData/refactoring/inlineLayout/MyActivity.java
@@ -0,0 +1,12 @@
+package p1.p2;
+
+import android.app.Activity;
+import android.view.View;
+
+public class MyActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ int n = R.layout.included;
+ }
+}
diff --git a/plugins/android/testSrc/org/jetbrains/android/refactoring/AndroidInlineLayoutTest.java b/plugins/android/testSrc/org/jetbrains/android/refactoring/AndroidInlineLayoutTest.java
new file mode 100644
index 000000000000..0ee42919cb2f
--- /dev/null
+++ b/plugins/android/testSrc/org/jetbrains/android/refactoring/AndroidInlineLayoutTest.java
@@ -0,0 +1,192 @@
+package org.jetbrains.android.refactoring;
+
+import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.refactoring.actions.InlineAction;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.android.AndroidTestCase;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class AndroidInlineLayoutTest extends AndroidTestCase {
+ private static final String BASE_PATH = "refactoring/inlineLayout/";
+
+ public void test1() throws Exception {
+ doTestCommonInlineThisOnly();
+ }
+
+ public void test2() throws Exception {
+ doTestCommonInlineThisOnly();
+ }
+
+ public void test3() throws Exception {
+ doTestCommonInlineThisOnly();
+ }
+
+ public void test4() throws Exception {
+ doTestCommonInlineThisOnly();
+ }
+
+ public void test5() throws Exception {
+ doTestCommonInlineThisOnly();
+ }
+
+ public void test6() throws Exception {
+ doTestCommonInlineThisOnly();
+ }
+
+ public void test7() throws Exception {
+ doTestCommonInlineThisOnly();
+ }
+
+ public void test8() throws Exception {
+ doTestCommonInlineAll();
+ }
+
+ public void test9() throws Exception {
+ final String testName = getTestName(true);
+ myFixture.copyFileToProject(BASE_PATH + testName + ".xml", "res/layout/test.xml");
+ final VirtualFile f = myFixture.copyFileToProject(BASE_PATH + testName + "_included.xml", "res/layout/included.xml");
+ myFixture.configureFromExistingVirtualFile(f);
+ AndroidInlineLayoutHandler.setTestConfig(new AndroidInlineTestConfig(true));
+ try {
+ final Presentation p = myFixture.testAction(new InlineAction());
+ assertTrue(p.isEnabled());
+ assertTrue(p.isVisible());
+ }
+ finally {
+ AndroidInlineLayoutHandler.setTestConfig(null);
+ }
+ myFixture.checkResultByFile("res/layout/test.xml", BASE_PATH + testName + "_after.xml", true);
+ assertNull(myFixture.getTempDirFixture().getFile("res/layout/included.xml"));
+ }
+
+ public void test10() throws Exception {
+ doTestCommonInlineThisOnly();
+ }
+
+ public void test11() throws Exception {
+ doTestCommonInlineThisOnly();
+ }
+
+ public void test12() throws Exception {
+ doTestCommonInlineThisOnly();
+ }
+
+ public void test13() throws Exception {
+ doTestCommonInlineThisOnly();
+ }
+
+ public void test14() throws Exception {
+ doTestCommonInlineThisOnly();
+ }
+
+ public void test15() throws Exception {
+ myFixture.copyFileToProject(BASE_PATH + getTestName(true) + "_included.xml", "res/layout-land/included.xml");
+ doTestCommonInlineActionError(false, true);
+ }
+
+ public void test16() throws Exception {
+ myFixture.copyFileToProject("R.java", "gen/p1/p2/R.java");
+ myFixture.copyFileToProject(BASE_PATH + "MyActivity.java", "src/p1/p2/MyActivity.java");
+ doTestCommonInlineActionError(false, true);
+ }
+
+ public void test17() throws Exception {
+ doTestInlineIncludeAction(true);
+ }
+
+ public void test18() throws Exception {
+ doTestInlineIncludeAction(false);
+ }
+
+ public void test19() throws Exception {
+ doTestInlineIncludeActionDisabled();
+ }
+
+ public void test20() throws Exception {
+ doTestInlineIncludeActionError(true);
+ }
+
+ private void doTestCommonInlineThisOnly() throws Exception {
+ doTestCommonInlineAction(true);
+ myFixture.checkResultByFile("res/layout/included.xml",
+ BASE_PATH + getTestName(true) + "_included.xml", true);
+ }
+
+ private void doTestCommonInlineAll() throws Exception {
+ doTestCommonInlineAction(false);
+ assertNull(myFixture.getTempDirFixture().getFile("res/layout/included.xml"));
+ }
+
+ private void doTestCommonInlineActionError(boolean inlineThisOnly, boolean configureFromIncludedFile) {
+ final String testName = getTestName(true);
+ final VirtualFile included = myFixture.copyFileToProject(BASE_PATH + testName + "_included.xml", "res/layout/included.xml");
+ final VirtualFile f = myFixture.copyFileToProject(BASE_PATH + testName + ".xml", "res/layout/test.xml");
+ myFixture.configureFromExistingVirtualFile(configureFromIncludedFile ? included : f);
+ AndroidInlineLayoutHandler.setTestConfig(new AndroidInlineTestConfig(inlineThisOnly));
+ try {
+ myFixture.testAction(new InlineAction());
+ fail();
+ }
+ catch (IncorrectOperationException e) {
+ assertTrue(e.getMessage().length() > 0);
+ }
+ finally {
+ AndroidInlineLayoutHandler.setTestConfig(null);
+ }
+ }
+
+ private void doTestCommonInlineAction(boolean inlineThisOnly) {
+ final String testName = getTestName(true);
+ myFixture.copyFileToProject(BASE_PATH + testName + "_included.xml", "res/layout/included.xml");
+ final VirtualFile f = myFixture.copyFileToProject(BASE_PATH + testName + ".xml", "res/layout/test.xml");
+ myFixture.configureFromExistingVirtualFile(f);
+ AndroidInlineLayoutHandler.setTestConfig(new AndroidInlineTestConfig(inlineThisOnly));
+ try {
+ final Presentation p = myFixture.testAction(new InlineAction());
+ assertTrue(p.isEnabled());
+ assertTrue(p.isVisible());
+ }
+ finally {
+ AndroidInlineLayoutHandler.setTestConfig(null);
+ }
+ myFixture.checkResultByFile(BASE_PATH + testName + "_after.xml", true);
+ }
+
+ private void doTestInlineIncludeAction(boolean inlineThisOnly) {
+ final String testName = getTestName(true);
+ myFixture.copyFileToProject(BASE_PATH + testName + "_included.xml", "res/layout/included.xml");
+ final VirtualFile f = myFixture.copyFileToProject(BASE_PATH + testName + ".xml", "res/layout/test.xml");
+ myFixture.configureFromExistingVirtualFile(f);
+ final Presentation p = myFixture.testAction(new AndroidInlineIncludeAction(new AndroidInlineTestConfig(inlineThisOnly)));
+ assertTrue(p.isEnabled());
+ assertTrue(p.isVisible());
+ myFixture.checkResultByFile(BASE_PATH + testName + "_after.xml", true);
+ }
+
+ private void doTestInlineIncludeActionDisabled() {
+ final String testName = getTestName(true);
+ myFixture.copyFileToProject(BASE_PATH + testName + "_included.xml", "res/layout/included.xml");
+ final VirtualFile f = myFixture.copyFileToProject(BASE_PATH + testName + ".xml", "res/layout/test.xml");
+ myFixture.configureFromExistingVirtualFile(f);
+ final Presentation p = myFixture.testAction(new AndroidInlineIncludeAction(new AndroidInlineTestConfig(true)));
+ assertTrue(p.isVisible());
+ assertFalse(p.isEnabled());
+ }
+
+ private void doTestInlineIncludeActionError(boolean inlineThisOnly) {
+ final String testName = getTestName(true);
+ myFixture.copyFileToProject(BASE_PATH + testName + "_included.xml", "res/layout/included.xml");
+ final VirtualFile f = myFixture.copyFileToProject(BASE_PATH + testName + ".xml", "res/layout/test.xml");
+ myFixture.configureFromExistingVirtualFile(f);
+ try {
+ myFixture.testAction(new AndroidInlineIncludeAction(new AndroidInlineTestConfig(inlineThisOnly)));
+ fail();
+ }
+ catch (IncorrectOperationException e) {
+ assertTrue(e.getMessage().length() > 0);
+ }
+ }
+}