package fr.adrienbrault.idea.symfony2plugin.config.xml; import com.intellij.codeInsight.completion.*; import com.intellij.openapi.project.Project; import com.intellij.patterns.PlatformPatterns; import com.intellij.patterns.XmlPatterns; 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.ProcessingContext; import com.jetbrains.php.lang.psi.elements.PhpClass; import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent; import fr.adrienbrault.idea.symfony2plugin.config.component.parser.ParameterLookupPercentElement; import fr.adrienbrault.idea.symfony2plugin.config.yaml.YamlCompletionContributor; import fr.adrienbrault.idea.symfony2plugin.dic.ContainerParameter; import fr.adrienbrault.idea.symfony2plugin.dic.ServiceCompletionProvider; import fr.adrienbrault.idea.symfony2plugin.dic.container.util.DotEnvUtil; import fr.adrienbrault.idea.symfony2plugin.form.util.FormUtil; import fr.adrienbrault.idea.symfony2plugin.stubs.ContainerCollectionResolver; import fr.adrienbrault.idea.symfony2plugin.util.SymfonyBundleFileCompletionProvider; import fr.adrienbrault.idea.symfony2plugin.util.completion.PhpClassAndParameterCompletionProvider; import fr.adrienbrault.idea.symfony2plugin.util.dict.ServiceUtil; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.NotNull; import java.util.Map; /** * @author Daniel Espendiller <daniel@espendiller.net> */ public class XmlCompletionContributor extends CompletionContributor { public XmlCompletionContributor() { extend(CompletionType.BASIC, XmlHelper.getTagPattern("class").inside(XmlHelper.getInsideTagPattern("services")), new PhpClassAndParameterCompletionProvider()); extend(CompletionType.BASIC, XmlHelper.getTagPattern("factory-service").inside(XmlHelper.getInsideTagPattern("services")), new ServiceCompletionProvider()); extend(CompletionType.BASIC, XmlHelper.getTagPattern("factory-class").inside(XmlHelper.getInsideTagPattern("services")), new PhpClassAndParameterCompletionProvider()); extend(CompletionType.BASIC, XmlHelper.getAutowiringTypePattern(), new PhpClassAndParameterCompletionProvider()); extend(CompletionType.BASIC, XmlHelper.getTagPattern("parent").inside(XmlHelper.getInsideTagPattern("services")), new ServiceCompletionProvider()); // <argument type="service" id="<caret>" /> // <factory service="<caret>" /> extend(CompletionType.BASIC, PlatformPatterns.psiElement().withParent(PlatformPatterns.or( XmlHelper.getArgumentServiceIdPattern(), XmlHelper.getFactoryServiceCompletionPattern(), XmlHelper.getArgumentServiceIdForArgumentPattern() )), new ServiceCompletionProvider()); extend(CompletionType.BASIC, XmlHelper.getTagAttributePattern("tag", "alias").inside(XmlHelper.getInsideTagPattern("services")), new FormAliasParametersCompletionProvider()); extend(CompletionType.BASIC, XmlHelper.getArgumentValuePattern(), new ArgumentParameterCompletionProvider()); extend( CompletionType.BASIC, XmlPatterns.psiElement().withParent(XmlHelper.getImportResourcePattern()), new SymfonyBundleFileCompletionProvider("Resources/config", "Controller") ); extend( CompletionType.BASIC, XmlPatterns.psiElement().withParent(XmlHelper.getImportResourcePattern()), new YamlCompletionContributor.DirectoryScopeCompletionProvider() ); } private static class FormAliasParametersCompletionProvider extends CompletionProvider<CompletionParameters> { @Override protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, final @NotNull CompletionResultSet completionResultSet) { PsiElement psiElement = completionParameters.getOriginalPosition(); if(psiElement == null || !Symfony2ProjectComponent.isEnabled(psiElement)) { return; } XmlTag xmlTag = PsiTreeUtil.getParentOfType(psiElement, XmlTag.class); if(xmlTag == null) { return; } XmlTag xmlTagService = PsiTreeUtil.getParentOfType(xmlTag, XmlTag.class); if(xmlTagService != null) { XmlAttribute xmlAttribute = xmlTagService.getAttribute("class"); if(xmlAttribute != null) { String value = xmlAttribute.getValue(); if(value != null && StringUtils.isNotBlank(value)) { PhpClass phpClass = ServiceUtil.getResolvedClassDefinition(psiElement.getProject(), value); if(phpClass != null) { FormUtil.attachFormAliasesCompletions(phpClass, completionResultSet); } } } } } } /** * <argument>%</argument> * <argument></argument> */ private static class ArgumentParameterCompletionProvider extends CompletionProvider<CompletionParameters> { @Override protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) { PsiElement psiElement = completionParameters.getOriginalPosition(); if(psiElement == null || !Symfony2ProjectComponent.isEnabled(psiElement)) { return; } Project project = psiElement.getProject(); for( Map.Entry<String, ContainerParameter> entry: ContainerCollectionResolver.getParameters(project).entrySet()) { completionResultSet.addElement( new ParameterLookupPercentElement(entry.getValue()) ); } // %env('foobar')% for (String s : DotEnvUtil.getEnvironmentVariables(project)) { completionResultSet.addElement(new ParameterLookupPercentElement(new ContainerParameter("env(" + s +")", false))); } } } }