Package fr.adrienbrault.idea.symfony2plugin.form

Source Code of fr.adrienbrault.idea.symfony2plugin.form.FormGotoCompletionRegistrar$FormOptionsGotoCompletionProvider

package fr.adrienbrault.idea.symfony2plugin.form;

import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.php.lang.PhpLanguage;
import com.jetbrains.php.lang.psi.elements.Method;
import com.jetbrains.php.lang.psi.elements.PhpClass;
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
import fr.adrienbrault.idea.symfony2plugin.Symfony2InterfacesUtil;
import fr.adrienbrault.idea.symfony2plugin.codeInsight.GotoCompletionContributor;
import fr.adrienbrault.idea.symfony2plugin.codeInsight.GotoCompletionProvider;
import fr.adrienbrault.idea.symfony2plugin.codeInsight.GotoCompletionRegistrar;
import fr.adrienbrault.idea.symfony2plugin.codeInsight.GotoCompletionRegistrarParameter;
import fr.adrienbrault.idea.symfony2plugin.form.util.FormOptionsUtil;
import fr.adrienbrault.idea.symfony2plugin.form.util.FormUtil;
import fr.adrienbrault.idea.symfony2plugin.util.MethodMatcher;
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;

public class FormGotoCompletionRegistrar implements GotoCompletionRegistrar {

    public void register(GotoCompletionRegistrarParameter registrar) {

        // FormBuilderInterface:add("", "type")
        registrar.register(PlatformPatterns.psiElement().withParent(StringLiteralExpression.class).withLanguage(PhpLanguage.INSTANCE), new GotoCompletionContributor() {
            @Nullable
            @Override
            public GotoCompletionProvider getProvider(@NotNull PsiElement psiElement) {

                PsiElement parent = psiElement.getParent();
                if(parent == null) {
                    return null;
                }

                MethodMatcher.MethodMatchParameter methodMatchParameter = new MethodMatcher.StringParameterMatcher(parent, 1)
                    .withSignature(Symfony2InterfacesUtil.getFormBuilderInterface())
                    .match();

                if(methodMatchParameter == null) {
                    return null;
                }

                return new FormBuilderAddGotoCompletionProvider(parent);
            }
        });

        /**
         * $options lookup
         * public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array())
         */
        registrar.register(PlatformPatterns.psiElement().withParent(StringLiteralExpression.class).withLanguage(PhpLanguage.INSTANCE), new GotoCompletionContributor() {
            @Nullable
            @Override
            public GotoCompletionProvider getProvider(@NotNull PsiElement psiElement) {

                PsiElement parent = psiElement.getParent();
                if(!(parent instanceof StringLiteralExpression)) {
                    return null;
                }

                MethodMatcher.MethodMatchParameter methodMatchParameter = new MethodMatcher.ArrayParameterMatcher(parent, 3)
                    .withSignature("\\Symfony\\Component\\Form\\FormFactoryInterface", "createNamedBuilder")
                    .withSignature("\\Symfony\\Component\\Form\\FormFactoryInterface", "createNamed")
                    .match();

                if(methodMatchParameter == null) {
                    return null;
                }

                return getFormProvider((StringLiteralExpression) parent, methodMatchParameter.getParameters()[1]);

            }

        });


        /**
         * $this->createForm(new FormType(), $entity, array('<foo_key>' => ''));
         * $this->createForm('foo', $entity, array('<foo_key>'));
         */
        registrar.register(PlatformPatterns.psiElement().withParent(StringLiteralExpression.class).withLanguage(PhpLanguage.INSTANCE), new GotoCompletionContributor() {
            @Nullable
            @Override
            public GotoCompletionProvider getProvider(@NotNull PsiElement psiElement) {

                PsiElement parent = psiElement.getParent();
                if(!(parent instanceof StringLiteralExpression)) {
                    return null;
                }

                MethodMatcher.MethodMatchParameter methodMatchParameter = new MethodMatcher.ArrayParameterMatcher(parent, 2)
                    .withSignature("\\Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller", "createForm")
                    .withSignature("\\Symfony\\Component\\Form\\FormFactoryInterface", "create")
                    .withSignature("\\Symfony\\Component\\Form\\FormFactory", "createBuilder")
                    .match();

                if(methodMatchParameter == null) {
                    return null;
                }

                return getFormProvider((StringLiteralExpression) parent, methodMatchParameter.getParameters()[0]);

            }

        });

        /**
         * FormTypeInterface::getParent
         */
        registrar.register(PlatformPatterns.psiElement().withParent(StringLiteralExpression.class).withLanguage(PhpLanguage.INSTANCE), new GotoCompletionContributor() {
            @Nullable
            @Override
            public GotoCompletionProvider getProvider(@NotNull PsiElement psiElement) {

                PsiElement parent = psiElement.getParent();
                if(!(parent instanceof StringLiteralExpression|| !PhpElementsUtil.getMethodReturnPattern().accepts(parent)) {
                    return null;
                }

                Method method = PsiTreeUtil.getParentOfType(psiElement, Method.class);
                if(method == null) {
                    return null;
                }

                if(!new Symfony2InterfacesUtil().isCallTo(method, "\\Symfony\\Component\\Form\\FormTypeInterface", "getParent")) {
                    return null;
                }

                return new FormBuilderAddGotoCompletionProvider(parent);

            }

        });


        /**
         * $type lookup
         * public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array())
         */
        registrar.register(PlatformPatterns.psiElement().withParent(StringLiteralExpression.class).withLanguage(PhpLanguage.INSTANCE), new GotoCompletionContributor() {
            @Nullable
            @Override
            public GotoCompletionProvider getProvider(@NotNull PsiElement psiElement) {

                PsiElement parent = psiElement.getParent();
                if(!(parent instanceof StringLiteralExpression)) {
                    return null;
                }

                MethodMatcher.MethodMatchParameter methodMatchParameter = new MethodMatcher.StringParameterMatcher(parent, 1)
                    .withSignature("\\Symfony\\Component\\Form\\FormFactoryInterface", "createNamedBuilder")
                    .withSignature("\\Symfony\\Component\\Form\\FormFactoryInterface", "createNamed")
                    .match();

                if(methodMatchParameter == null) {
                    return null;
                }

                return new FormBuilderAddGotoCompletionProvider(parent);

            }

        });

    }

    /**
     * Form options on extension or form type default options
     */
    private static class FormOptionsGotoCompletionProvider extends GotoCompletionProvider {

        private final String formType;
        private final Collection<FormOption> options;

        public FormOptionsGotoCompletionProvider(@NotNull PsiElement element, @NotNull String formType, FormOption... options) {
            super(element);
            this.formType = formType;
            this.options = Arrays.asList(options);
        }

        @NotNull
        @Override
        public Collection<LookupElement> getLookupElements() {

            Collection<LookupElement> lookupElements = new ArrayList<LookupElement>();

            if(options.contains(FormOption.EXTENSION)) {
                lookupElements.addAll(FormOptionsUtil.getFormExtensionKeysLookupElements(getElement().getProject(), this.formType));
            }

            if(options.contains(FormOption.DEFAULT_OPTIONS)) {
                lookupElements.addAll(FormOptionsUtil.getDefaultOptionLookupElements(getElement().getProject(), this.formType));
            }

            return lookupElements;
        }

        @NotNull
        @Override
        public Collection<PsiElement> getPsiTargets(PsiElement psiElement) {

            PsiElement element = psiElement.getParent();
            if(!(element instanceof StringLiteralExpression)) {
                return Collections.emptyList();
            }

            Collection<PsiElement> targets = new ArrayList<PsiElement>();

            if(options.contains(FormOption.EXTENSION)) {
                targets.addAll(FormOptionsUtil.getFormExtensionsKeysTargets((StringLiteralExpression) element, this.formType));
            }

            if(options.contains(FormOption.DEFAULT_OPTIONS)) {
                targets.addAll(FormOptionsUtil.getDefaultOptionTargets((StringLiteralExpression) element, this.formType));
            }

            return targets;

        }
    }

    /**
     * All registered form type with their getName() return alias name
     */
    private static class FormBuilderAddGotoCompletionProvider extends GotoCompletionProvider {

        public FormBuilderAddGotoCompletionProvider(PsiElement element) {
            super(element);
        }

        @NotNull
        @Override
        public Collection<LookupElement> getLookupElements() {
            return FormUtil.getFormTypeLookupElements(getElement().getProject());
        }

        @NotNull
        @Override
        public Collection<PsiElement> getPsiTargets(PsiElement psiElement) {

            PsiElement element = psiElement.getParent();
            if(!(element instanceof StringLiteralExpression)) {
                return Collections.emptyList();
            }

            PhpClass formTypeToClass = FormUtil.getFormTypeToClass(getElement().getProject(), ((StringLiteralExpression) element).getContents());
            if(formTypeToClass == null) {
                return Collections.emptyList();
            }

            return Arrays.asList(new PsiElement[] { formTypeToClass });
        }
    }

    private static enum FormOption {
        EXTENSION, DEFAULT_OPTIONS
    }

    private FormOptionsGotoCompletionProvider getFormProvider(StringLiteralExpression psiElement, PsiElement formType) {

        PhpClass phpClass = FormUtil.getFormTypeClassOnParameter(formType);
        if (phpClass == null) {
            return new FormOptionsGotoCompletionProvider(psiElement, "form", FormOption.EXTENSION);
        }

        String presentableFQN = phpClass.getPresentableFQN();
        if(presentableFQN == null) {
            presentableFQN = "form";
        }

        return new FormOptionsGotoCompletionProvider(psiElement, presentableFQN, FormOption.EXTENSION, FormOption.DEFAULT_OPTIONS);
    }
}
TOP

Related Classes of fr.adrienbrault.idea.symfony2plugin.form.FormGotoCompletionRegistrar$FormOptionsGotoCompletionProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.