package fr.adrienbrault.idea.symfony2plugin.intentions.xml;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
import fr.adrienbrault.idea.symfony2plugin.config.xml.XmlServiceContainerAnnotator;
import fr.adrienbrault.idea.symfony2plugin.intentions.php.XmlServiceArgumentIntention;
import fr.adrienbrault.idea.symfony2plugin.intentions.ui.ServiceSuggestDialog;
import fr.adrienbrault.idea.symfony2plugin.util.dict.ServiceUtil;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
/**
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class XmlServiceSuggestIntention extends PsiElementBaseIntentionAction {
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement psiElement) {
if(!Symfony2ProjectComponent.isEnabled(psiElement.getProject())) {
return false;
}
final XmlTag argumentTag = PsiTreeUtil.getParentOfType(psiElement, XmlTag.class);
if(argumentTag == null || !"argument".equals(argumentTag.getName())) {
return false;
}
return XmlServiceArgumentIntention.getServiceTagValid(psiElement) != null;
}
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement psiElement) throws IncorrectOperationException {
XmlTag xmlTag = XmlServiceArgumentIntention.getServiceTagValid(psiElement);
if (xmlTag == null) {
return;
}
XmlAttribute classAttribute = xmlTag.getAttribute("class");
if(classAttribute == null) {
return;
}
final XmlTag argumentTag = PsiTreeUtil.getParentOfType(psiElement, XmlTag.class);
if(argumentTag == null) {
return;
}
int argumentIndex = XmlServiceContainerAnnotator.getArgumentIndex(argumentTag);
String serviceName = classAttribute.getValue();
if(serviceName == null || StringUtils.isBlank(serviceName)) {
return;
}
Set<String> suggestions = ServiceUtil.getServiceSuggestionsForServiceConstructorIndex(project, serviceName, argumentIndex);
if(suggestions.size() == 0) {
HintManager.getInstance().showErrorHint(editor, "No suggestion found");
return;
}
ServiceSuggestDialog.create(editor, suggestions, new MyInsertCallback(argumentTag));
}
@NotNull
@Override
public String getFamilyName() {
return "Symfony";
}
@NotNull
@Override
public String getText() {
return "Symfony: Suggest Service";
}
public static class MyInsertCallback implements ServiceSuggestDialog.Callback {
private final XmlTag argumentTag;
public MyInsertCallback(XmlTag argumentTag) {
this.argumentTag = argumentTag;
}
@Override
public void insert(@NotNull String selected) {
// set type="service" for lazy devs
if(ContainerUtil.find(argumentTag.getAttributes(), xmlAttribute -> "type".equals(xmlAttribute.getName())) == null) {
argumentTag.setAttribute("type", "service");
}
// append type="SERVICE"
argumentTag.setAttribute("id", selected);
}
}
}