blob: f183f232b9592ac39d533953d2c391525db94fd6 [file] [log] [blame]
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.util.PsiUtilBase;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlToken;
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) {
return false;
}
@Override
public boolean canInlineElementInEditor(PsiElement element, Editor editor) {
if (element instanceof ResourceElementWrapper) {
element = ((ResourceElementWrapper)element).getWrappee();
}
if (element instanceof XmlFile) {
if (AndroidFacet.getInstance(element) == null ||
((XmlFile)element).getRootTag() == null) {
return false;
}
return DomManager.getDomManager(element.getProject()).getDomFileDescription((XmlFile)element)
instanceof LayoutDomFileDescription;
}
return getLayoutUsageDataFromContext(editor) != null;
}
@Nullable
private static LayoutUsageData getLayoutUsageDataFromContext(Editor editor) {
if (editor == null) {
return null;
}
final PsiElement element = PsiUtilBase.getElementAtCaret(editor);
if (!(element instanceof XmlToken) ||
AndroidFacet.getInstance(element) == null) {
return null;
}
final XmlTag tag = PsiTreeUtil.getParentOfType(element, 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(editor);
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, ref.getElement(), ourTestConfig);
}
}