Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -143,22 +143,24 @@ public static Collection<TwigTypeContainer> resolveTwigMethodName(@NotNull PsiEl

String rootType = types.iterator().next();
Collection<PsiVariable> rootVariables = getRootVariableByName(psiElement, rootType);
if(types.size() == 1) {
Collection<TwigTypeContainer> twigTypeContainers = TwigTypeContainer.fromCollection(psiElement.getProject(), rootVariables);
if (types.size() == 1) {
Project project = psiElement.getProject();
Collection<TwigTypeContainer> twigTypeContainers = TwigTypeContainer.fromCollection(project, rootVariables);
for(TwigTypeResolver twigTypeResolver: TWIG_TYPE_RESOLVERS) {
twigTypeResolver.resolve(twigTypeContainers, twigTypeContainers, rootType, new ArrayList<>(), rootVariables);
twigTypeResolver.resolve(project, twigTypeContainers, twigTypeContainers, rootType, new ArrayList<>(), rootVariables);
}

return twigTypeContainers;
}

Collection<TwigTypeContainer> type = TwigTypeContainer.fromCollection(psiElement.getProject(), rootVariables);
Project project = psiElement.getProject();
Collection<TwigTypeContainer> type = TwigTypeContainer.fromCollection(project, rootVariables);
Collection<List<TwigTypeContainer>> previousElements = new ArrayList<>();
previousElements.add(new ArrayList<>(type));

String[] typeNames = types.toArray(new String[0]);
for (int i = 1; i <= typeNames.length - 1; i++ ) {
type = resolveTwigMethodName(type, typeNames[i], previousElements);
type = resolveTwigMethodName(project, type, typeNames[i], previousElements);
previousElements.add(new ArrayList<>(type));

// we can stop on empty list
Expand Down Expand Up @@ -538,7 +540,7 @@ private static Collection<PsiVariable> getRootVariableByName(@NotNull PsiElement
return phpNamedElements;
}

private static Collection<TwigTypeContainer> resolveTwigMethodName(Collection<TwigTypeContainer> previousElement, String typeName, Collection<List<TwigTypeContainer>> twigTypeContainer) {
private static Collection<TwigTypeContainer> resolveTwigMethodName(@NotNull Project project, Collection<TwigTypeContainer> previousElement, String typeName, Collection<List<TwigTypeContainer>> twigTypeContainer) {

ArrayList<TwigTypeContainer> phpNamedElements = new ArrayList<>();

Expand All @@ -565,7 +567,7 @@ private static Collection<TwigTypeContainer> resolveTwigMethodName(Collection<Tw
}

for(TwigTypeResolver twigTypeResolver: TWIG_TYPE_RESOLVERS) {
twigTypeResolver.resolve(phpNamedElements, previousElement, typeName, twigTypeContainer, null);
twigTypeResolver.resolve(project, phpNamedElements, previousElement, typeName, twigTypeContainer, null);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,18 @@
*/
public class FormFieldResolver implements TwigTypeResolver {

public void resolve(Collection<TwigTypeContainer> targets, Collection<TwigTypeContainer> previousElement, String typeName, Collection<List<TwigTypeContainer>> previousElements, @Nullable Collection<PsiVariable> psiVariables) {
public void resolve(@NotNull Project project, Collection<TwigTypeContainer> targets, Collection<TwigTypeContainer> previousElement, String typeName, Collection<List<TwigTypeContainer>> previousElements, @Nullable Collection<PsiVariable> psiVariables) {
if (targets.isEmpty() || previousElements == null || !previousElements.isEmpty()) {
return;
}

TwigTypeContainer twigTypeContainer = targets.iterator().next();
if (
twigTypeContainer.getPhpNamedElement() instanceof PhpClass phpClass &&
isFormView(phpClass) &&
twigTypeContainer.getFormViewDataHolder() instanceof FormViewDataHolder formViewDataHolder &&
!formViewDataHolder.formTypeFqns().isEmpty()
) {
visitFormFields(phpClass.getProject(), formViewDataHolder.formTypeFqns(), field -> targets.add(toTwigTypeContainer(field)));
FormViewDataHolder formViewDataHolder = twigTypeContainer.getFormViewDataHolder();
if (formViewDataHolder == null || formViewDataHolder.formTypeFqns().isEmpty()) {
return;
}
}

public static boolean isFormView(@NotNull PhpClass phpClass) {
return PhpElementsUtil.isInstanceOf(phpClass, "\\Symfony\\Component\\Form\\FormView") ||
PhpElementsUtil.isInstanceOf(phpClass, "\\Symfony\\Component\\Form\\FormInterface"); // form view is create converting by Symfony on template render
visitFormFields(project, formViewDataHolder.formTypeFqns(), field -> targets.add(toTwigTypeContainer(field)));
}

public static boolean isFormView(@NotNull PhpType phpType) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver;

import com.intellij.openapi.project.Project;
import com.jetbrains.php.lang.psi.elements.PhpClass;
import fr.adrienbrault.idea.symfony2plugin.form.util.FormOptionsUtil;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.TwigTypeContainer;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.dict.PsiVariable;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver.holder.FormViewDataHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
Expand All @@ -14,7 +15,7 @@
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class FormVarsResolver implements TwigTypeResolver {
public void resolve(Collection<TwigTypeContainer> targets, Collection<TwigTypeContainer> previousElement, String typeName, Collection<List<TwigTypeContainer>> previousElements, @Nullable Collection<PsiVariable> psiVariables) {
public void resolve(@NotNull Project project, Collection<TwigTypeContainer> targets, Collection<TwigTypeContainer> previousElement, String typeName, Collection<List<TwigTypeContainer>> previousElements, @Nullable Collection<PsiVariable> psiVariables) {
if(!"vars".equals(typeName) || previousElements.isEmpty()) {
return;
}
Expand All @@ -25,10 +26,9 @@ public void resolve(Collection<TwigTypeContainer> targets, Collection<TwigTypeCo
}

for (TwigTypeContainer twigTypeContainer: lastTwigTypeContainer) {
if (twigTypeContainer.getPhpNamedElement() instanceof PhpClass) {
if (FormFieldResolver.isFormView((PhpClass) twigTypeContainer.getPhpNamedElement())) {
attachVars(twigTypeContainer.getPhpNamedElement().getProject(), targets);
}
FormViewDataHolder formViewDataHolder = twigTypeContainer.getFormViewDataHolder();
if (formViewDataHolder != null && !formViewDataHolder.formTypeFqns().isEmpty()) {
attachVars(project, targets);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver;

import com.intellij.openapi.project.Project;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.TwigTypeContainer;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.dict.PsiVariable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
Expand All @@ -11,5 +13,5 @@
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public interface TwigTypeResolver {
void resolve(Collection<TwigTypeContainer> targets, @Nullable Collection<TwigTypeContainer> previousElement, String typeName, Collection<List<TwigTypeContainer>> previousElements, @Nullable Collection<PsiVariable> psiVariables);
void resolve(@NotNull Project project, Collection<TwigTypeContainer> targets, @Nullable Collection<TwigTypeContainer> previousElement, String typeName, Collection<List<TwigTypeContainer>> previousElements, @Nullable Collection<PsiVariable> psiVariables);
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public void testResolveUsesPrimitiveFormTypeFqnsWithoutPsiElement() {
assertNotNull(rootFormDataHolder);
assertContainsElements(rootFormDataHolder.formTypeFqns(), "\\App\\Form\\ProductType");

new FormFieldResolver().resolve(targets, targets, "form", new ArrayList<>(), null);
new FormFieldResolver().resolve(getProject(), targets, targets, "form", new ArrayList<>(), null);

TwigTypeContainer title = targets.stream()
.filter(twigTypeContainer -> "title".equals(twigTypeContainer.getStringElement()))
Expand All @@ -117,6 +117,28 @@ public void testResolveUsesPrimitiveFormTypeFqnsWithoutPsiElement() {
assertEquals("\\App\\Form\\ProductType", formFieldDataHolder.ownerFormTypeFqn());
}

public void testResolveDoesNotUseFormViewClassWithoutFormViewDataHolder() {
myFixture.configureByText(PhpFileType.INSTANCE, "<?php\n" +
"namespace Symfony\\Component\\Form { class FormView {} interface FormTypeInterface {} interface FormBuilderInterface { public function add(); } }\n" +
"namespace App\\Form {\n" +
" class ProductType implements \\Symfony\\Component\\Form\\FormTypeInterface {\n" +
" public function buildForm(\\Symfony\\Component\\Form\\FormBuilderInterface $builder, array $options) {\n" +
" $builder->add('title');\n" +
" }\n" +
" }\n" +
"}\n"
);

Collection<TwigTypeContainer> targets = TwigTypeContainer.fromCollection(
getProject(),
Collections.singleton(new PsiVariable("\\Symfony\\Component\\Form\\FormView"))
);

new FormFieldResolver().resolve(getProject(), targets, targets, "form", new ArrayList<>(), null);

assertFalse(targets.stream().anyMatch(twigTypeContainer -> "title".equals(twigTypeContainer.getStringElement())));
}

@NotNull
private MethodReference findMethodReference(@NotNull String name) {
for (PsiElement psiElement : PsiTreeUtil.collectElementsOfType(myFixture.getFile(), MethodReference.class)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package fr.adrienbrault.idea.symfony2plugin.tests.templating.variable.resolver;

import com.jetbrains.php.lang.PhpFileType;
import com.jetbrains.php.lang.psi.elements.PhpClass;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.TwigTypeContainer;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver.FormVarsResolver;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver.holder.FormViewDataHolder;
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;

import java.util.ArrayList;
import java.util.Collections;

/**
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class FormVarsResolverTest extends SymfonyLightCodeInsightFixtureTestCase {
public void testResolveAttachesFormVarsForFormViewDataHolder() {
configureFormViewVarsFixture();

ArrayList<TwigTypeContainer> targets = new ArrayList<>();
new FormVarsResolver().resolve(
getProject(),
targets,
null,
"vars",
Collections.singletonList(Collections.singletonList(createRootFormViewContainer(true))),
null
);

assertContainsElements(
targets.stream().map(TwigTypeContainer::getStringElement).toList(),
"compound",
"form_attr"
);
}

public void testResolveDoesNotUseFormViewClassWithoutFormViewDataHolder() {
configureFormViewVarsFixture();

ArrayList<TwigTypeContainer> targets = new ArrayList<>();
new FormVarsResolver().resolve(
getProject(),
targets,
null,
"vars",
Collections.singletonList(Collections.singletonList(createRootFormViewContainer(false))),
null
);

assertEmpty(targets);
}

private void configureFormViewVarsFixture() {
myFixture.configureByText(PhpFileType.INSTANCE, "<?php\n" +
"namespace Symfony\\Component\\Form {\n" +
" interface FormTypeInterface { public function getName(); }\n" +
" class FormView { public $vars = []; }\n" +
"}\n" +
"namespace Symfony\\Component\\Form\\Extension\\Core\\Type {\n" +
" class FormType implements \\Symfony\\Component\\Form\\FormTypeInterface {\n" +
" public function getName() { return 'form'; }\n" +
" public function buildView(\\Symfony\\Component\\Form\\FormView $view, $form, array $options) {\n" +
" $view->vars['form_attr'] = true;\n" +
" $view->vars = array_replace($view->vars, ['compound' => true]);\n" +
" }\n" +
" }\n" +
"}\n"
);
}

private TwigTypeContainer createRootFormViewContainer(boolean withFormViewDataHolder) {
PhpClass phpClass = PhpElementsUtil.getClass(getProject(), "\\Symfony\\Component\\Form\\FormView");
assertNotNull(phpClass);

return new TwigTypeContainer(
phpClass,
withFormViewDataHolder ? new FormViewDataHolder(Collections.singleton("\\App\\Form\\ProductType")) : null
);
}
}
Loading