Skip to content

WIP: form field navigation and linemarker for Twig #1530

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
@@ -110,6 +110,11 @@ public void collectSlowLineMarkers(@NotNull List<PsiElement> psiElements, @NotNu
if(lineOverwrites != null) {
results.add(lineOverwrites);
}
} else if(TwigPattern.getFunctionPattern("form_row", "form_widget").accepts(psiElement)) {
LineMarkerInfo lineOverwrites = attachFormTypeFields(psiElement);
if(lineOverwrites != null) {
results.add(lineOverwrites);
}
}
}
}
@@ -299,7 +304,45 @@ private LineMarkerInfo attachBlockOverwrites(@NotNull PsiElement psiElement, @No

NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(PhpIcons.OVERRIDES)
.setTargets(new BlockOverwriteLazyValue(psiElement))
.setTooltipText("Overwrites")
.setTooltipText("Navigate to form")
.setCellRenderer(new MyBlockListCellRenderer());

return builder.createLineMarkerInfo(firstChild);
}

@Nullable
private LineMarkerInfo attachFormTypeFields(@NotNull PsiElement psiElement) {
PsiElement firstChild = psiElement.getFirstChild();
if (firstChild == null) {
return null;
}

PsiElement nextSiblingOfType = PsiElementUtils.getNextSiblingOfType(firstChild, PlatformPatterns.psiElement().withElementType(TwigTokenTypes.IDENTIFIER).beforeLeaf(PlatformPatterns.psiElement(TwigTokenTypes.RBRACE)));
if (nextSiblingOfType == null) {
return null;
}

Collection<TwigTypeContainer> twigTypeContainers = TwigTypeResolveUtil.resolveTwigMethodName(nextSiblingOfType, TwigTypeResolveUtil.formatPsiTypeNameWithCurrent(nextSiblingOfType));

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

for (TwigTypeContainer twigTypeContainer : twigTypeContainers) {
Object dataHolder = twigTypeContainer.getDataHolder();
if (dataHolder instanceof FormDataHolder && PhpElementsUtil.isInstanceOf(((FormDataHolder) dataHolder).getFormType(), "\\Symfony\\Component\\Form\\FormTypeInterface")) {
PsiElement field = ((FormDataHolder) dataHolder).getField();
if (field != null) {
targets.add(field);
}
}
}

if (targets.isEmpty()) {
return null;
}

NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Symfony2Icons.FORM_TYPE_LINE_MARKER)
.setTargets(targets)
.setTooltipText("Navigate to form field")
.setCellRenderer(new MyBlockListCellRenderer());

return builder.createLineMarkerInfo(psiElement);
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
import com.jetbrains.php.lang.psi.elements.PhpNamedElement;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.dict.PsiVariable;
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
@@ -15,16 +16,20 @@
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class TwigTypeContainer {

@Nullable
private PhpNamedElement phpNamedElement;

@Nullable
private String stringElement;

@Nullable
private Object dataHolder;

public TwigTypeContainer(PhpNamedElement phpNamedElement) {
public TwigTypeContainer(@Nullable PhpNamedElement phpNamedElement) {
this.phpNamedElement = phpNamedElement;
}

public TwigTypeContainer(String stringElement) {
public TwigTypeContainer(@Nullable String stringElement) {
this.stringElement = stringElement;
}

@@ -52,11 +57,12 @@ public static Collection<TwigTypeContainer> fromCollection(Project project, Coll
return twigTypeContainerList;
}

public TwigTypeContainer withDataHolder(Object object) {
public TwigTypeContainer withDataHolder(@NotNull Object object) {
this.dataHolder = object;
return this;
}

@Nullable
public Object getDataHolder() {
return dataHolder;
}
Original file line number Diff line number Diff line change
@@ -123,20 +123,23 @@ private static void attachFormFields(@Nullable MethodReference methodReference,
}

@NotNull
private static List<TwigTypeContainer> getTwigTypeContainer(@NotNull Method method, @NotNull PhpClass formTypClass) {
List<TwigTypeContainer> twigTypeContainers = new ArrayList<>();
private static Collection<TwigTypeContainer> getTwigTypeContainer(@NotNull Method method, @NotNull PhpClass formTypClass) {
Collection<TwigTypeContainer> twigTypeContainers = new ArrayList<>();

for(MethodReference methodReference: FormUtil.getFormBuilderTypes(method)) {

String fieldName = PsiElementUtils.getMethodParameterAt(methodReference, 0);
if (fieldName == null) {
continue;
}

PsiElement psiElement = PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 1);
TwigTypeContainer twigTypeContainer = new TwigTypeContainer(fieldName);

// find form field type
if(psiElement != null) {
PhpClass fieldType = FormUtil.getFormTypeClassOnParameter(psiElement);
if(fieldType != null) {
twigTypeContainer.withDataHolder(new FormDataHolder(fieldType, formTypClass));
twigTypeContainer.withDataHolder(new FormDataHolder(fieldType, formTypClass, psiElement));
}
}

Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver.holder;

import com.intellij.psi.PsiElement;
import com.jetbrains.php.lang.psi.elements.PhpClass;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* @author Daniel Espendiller <daniel@espendiller.net>
@@ -13,11 +15,20 @@ public class FormDataHolder {
@NotNull
private final PhpClass formType;

@Nullable
private PsiElement field;

public FormDataHolder(@NotNull PhpClass phpClass, @NotNull PhpClass formType) {
this.phpClass = phpClass;
this.formType = formType;
}

public FormDataHolder(@NotNull PhpClass phpClass, @NotNull PhpClass formType, @NotNull PsiElement field) {
this.phpClass = phpClass;
this.formType = formType;
this.field = field;
}

@NotNull
public PhpClass getPhpClass() {
return phpClass;
@@ -27,4 +38,9 @@ public PhpClass getPhpClass() {
public PhpClass getFormType() {
return formType;
}

@Nullable
public PsiElement getField() {
return this.field;
}
}