From 40d414409b6a8a084d664c13cfba98dd6fc8d262 Mon Sep 17 00:00:00 2001 From: Daniel Espendiller Date: Sun, 5 May 2024 15:06:36 +0200 Subject: [PATCH] form builder field completion, should support function+property types and greyout already existing fields --- .../PhpIncompleteCompletionContributor.java | 31 +++++++++++++++++-- .../symfony2plugin/form/util/FormUtil.java | 16 +++++++++- .../variable/resolver/FormFieldResolver.java | 2 +- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/completion/PhpIncompleteCompletionContributor.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/completion/PhpIncompleteCompletionContributor.java index f13374aca..3b1588065 100644 --- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/completion/PhpIncompleteCompletionContributor.java +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/completion/PhpIncompleteCompletionContributor.java @@ -20,6 +20,7 @@ import fr.adrienbrault.idea.symfony2plugin.form.FormUnderscoreMethodReference; import fr.adrienbrault.idea.symfony2plugin.form.util.FormOptionsUtil; import fr.adrienbrault.idea.symfony2plugin.form.util.FormUtil; +import fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver.FormFieldResolver; import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil; import kotlin.Pair; import org.apache.commons.lang3.StringUtils; @@ -60,9 +61,24 @@ protected void addCompletions(@NotNull CompletionParameters completionParameters return; } + Set alreadyKnownFields = new HashSet<>(); + String formTypeClassFromScope = FormUtil.getFormTypeClassFromScope(parent); + if (formTypeClassFromScope != null) { + PhpClass clazz = PhpElementsUtil.getClassInterface(project, formTypeClassFromScope); + if (clazz != null) { + FormFieldResolver.visitFormReferencesFields(clazz, twigTypeContainer -> alreadyKnownFields.add(twigTypeContainer.getStringElement())); + } + } + FormUnderscoreMethodReference.visitPropertyPath( phpClass, - pair -> completionResultSet.addElement(new MyLookupElement(pair.getFirst(), "add", pair.getSecond(), phpClass.getName())) + pair -> completionResultSet.addElement(new MyLookupElement( + pair.getFirst(), + "add", + pair.getSecond(), + phpClass.getName(), + alreadyKnownFields.contains(pair.getFirst()) + )) ); } } @@ -140,19 +156,28 @@ private class MyLookupElement extends com.intellij.codeInsight.lookup.LookupElem private final PhpNamedElement phpNamedElement; private final String typeText; + private final @NotNull boolean exists; - public MyLookupElement(@NotNull String key, @NotNull String lookupElement, @NotNull PhpNamedElement phpNamedElement, @NotNull String typeText) { + public MyLookupElement(@NotNull String key, @NotNull String lookupElement, @NotNull PhpNamedElement phpNamedElement, @NotNull String typeText, boolean exists) { this.key = key; this.lookupElement = lookupElement; this.phpNamedElement = phpNamedElement; this.typeText = typeText; + this.exists = exists; } @Override public void renderElement(@NotNull LookupElementPresentation presentation) { super.renderElement(presentation); + + if (this.exists) { + presentation.setTypeText(typeText, Symfony2Icons.SYMFONY_AI_OPACITY); + presentation.setTypeGrayed(true); + } else { + presentation.setTypeText(typeText, Symfony2Icons.SYMFONY_AI); + } + presentation.setIcon(phpNamedElement.getIcon()); - presentation.setTypeText(typeText, Symfony2Icons.SYMFONY); presentation.setTypeIconRightAligned(true); } diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/form/util/FormUtil.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/form/util/FormUtil.java index d1187d8bf..67444a558 100644 --- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/form/util/FormUtil.java +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/form/util/FormUtil.java @@ -760,7 +760,21 @@ public static Collection getFormTypeParentFromFormTypeImplementation(@No } public static Pair> getGuessedFormFieldParameters(@NotNull PhpIndex phpIndex, @NotNull Project project, @NotNull String key, @NotNull PhpNamedElement phpNamedElement) { - PhpType phpType = phpIndex.completeType(project, phpNamedElement.getType(), new HashSet<>()); + // method / function + PhpType phpType = null; + if (phpNamedElement instanceof Function function) { + PsiElement parameter = function.getParameter(0); + if (parameter instanceof PhpTypedElement phpTypedElement) { + phpType = phpIndex.completeType(project, phpTypedElement.getType(), new HashSet<>()); + } + } else { + // properties + phpType = phpIndex.completeType(project, phpNamedElement.getType(), new HashSet<>()); + } + + if (phpType == null) { + return new Pair<>("\\Symfony\\Component\\Form\\Extension\\Core\\Type\\TextType", null); + } String typeClass = null; Map options = new HashMap<>(); diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/variable/resolver/FormFieldResolver.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/variable/resolver/FormFieldResolver.java index aa9c6a004..9b18c1f5a 100644 --- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/variable/resolver/FormFieldResolver.java +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/variable/resolver/FormFieldResolver.java @@ -188,7 +188,7 @@ public static void visitFormReferencesFields(@NotNull PsiElement formReference, } /** - * Field all form fields in given PhpClass which should already be just a form type + * Visit all form fields in given PhpClass which are already a form type */ public static void visitFormReferencesFields(@NotNull PhpClass phpClass, @NotNull Consumer consumer) { visitFormReferencesFields(phpClass.getProject(), Collections.singleton(phpClass), consumer);