Skip to content

Commit

Permalink
Merge pull request #2225 from Haehnchen/feature/component-block
Browse files Browse the repository at this point in the history
provide block support inside Symfony UX component tag
  • Loading branch information
Haehnchen authored Sep 17, 2023
2 parents 0c045f1 + 754452f commit eb2d5c6
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,42 @@ public static PsiElement getTransDefaultDomainScope(@NotNull PsiElement psiEleme
);
}

/**
* File Scope:
* {% trans_default_domain "foo" %}
*
* Embed:
* {embed 'foo.html.twig'}{% trans_default_domain "foo" %}{% endembed %}
*/
@Nullable
public static PsiElement getBlockExtendsScope(@NotNull PsiElement psiElement) {
return PsiTreeUtil.findFirstParent(psiElement, psiElement1 -> {
if (psiElement1 instanceof PsiFile) {
return true;
}

// {% embed "test.html.twig" %}
if (psiElement1 instanceof TwigCompositeElement && psiElement1.getNode().getElementType() == TwigElementTypes.EMBED_STATEMENT) {
return true;
}

// {% component DataTable with
if (psiElement1 instanceof TwigStatement && psiElement1.getNode().getElementType() instanceof TwigTag) {
PsiElement firstChild = psiElement1.getFirstChild();
if (firstChild != null && firstChild.getNode().getElementType() == TwigElementTypes.TAG) {
PsiElement firstChild1 = firstChild.getFirstChild();
if (firstChild1 != null) {
PsiElement tagName = PsiElementUtils.getNextSiblingAndSkip(firstChild1, TwigTokenTypes.TAG_NAME);
return tagName != null && "component".equals(tagName.getText());
}
}
}

return false;
}
);
}

/**
* need a twig translation print block and search for default domain on parameter or trans_default_domain
*
Expand Down Expand Up @@ -1843,19 +1879,37 @@ private static Collection<String> getTernaryStrings(@NotNull PsiElement psiQuest
public static Pair<Collection<PsiFile>, Boolean> findScopedFile(@NotNull PsiElement psiElement) {

// {% embed "template.twig" %}{% block <caret> %}
PsiElement firstParent = getTransDefaultDomainScope(psiElement);
PsiElement firstParent = getBlockExtendsScope(psiElement);

// {% embed "template.twig" %}
if(firstParent != null && firstParent.getNode().getElementType() == TwigElementTypes.EMBED_STATEMENT) {
if (firstParent != null && firstParent.getNode().getElementType() == TwigElementTypes.EMBED_STATEMENT) {
PsiElement embedTag = firstParent.getFirstChild();
if(embedTag != null) {
if (embedTag != null) {
String templateName = getTemplateNameForEmbedTag(embedTag);
if(templateName != null) {
if (templateName != null) {
return Pair.create(getTemplatePsiElements(psiElement.getProject(), templateName), true);
}
}

return Pair.create(Collections.emptyList(), true);
} else if (firstParent != null) {
// {% component RandomNumber
PsiElement firstChild = firstParent.getFirstChild();
if (firstChild != null) {
PsiElement tagStart = firstChild.getFirstChild();
if (tagStart != null) {
PsiElement tagName = PsiElementUtils.getNextSiblingAndSkip(tagStart, TwigTokenTypes.TAG_NAME);
if (tagName != null && "component".equals(tagName.getText())) {
PsiElement filterName = PsiTreeUtil.nextVisibleLeaf(tagName);
if (filterName != null) {
String componentName = PsiElementUtils.trimQuote(filterName.getText());
if (!componentName.isBlank()) {
return Pair.create(UxUtil.getComponentTemplates(psiElement.getProject(), componentName), true);
}
}
}
}
}
}

return Pair.create(Collections.singletonList(psiElement.getContainingFile()), false);
Expand Down Expand Up @@ -2826,7 +2880,7 @@ public static Collection<LookupElement> getBlockLookupElements(@NotNull Project
.withIcon(TwigIcons.TwigFileIcon);

Collection<String> names = templateNames.getOrDefault(virtualFile, Collections.emptyList());
if(names.size() > 0) {
if(!names.isEmpty()) {
lookupElementBuilder = lookupElementBuilder.withTypeText(names.iterator().next(), true);
}

Expand Down
17 changes: 17 additions & 0 deletions src/main/java/fr/adrienbrault/idea/symfony2plugin/util/UxUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -128,6 +129,22 @@ private static Collection<UxComponent> getAllUxComponents(@NotNull Project proje
);
}

public static Collection<PsiFile> getComponentTemplates(@NotNull Project project, @NotNull String component) {
Collection<PsiFile> psiFiles = new HashSet<>();

for (UxComponent allUxComponent : getAllUxComponents(project).stream().filter(uxComponent -> component.equals(uxComponent.name())).toList()) {
String template = allUxComponent.template();

if (template != null) {
psiFiles.addAll(TwigUtil.getTemplatePsiElements(project, template));
} else {
psiFiles.addAll(TwigUtil.getTemplatePsiElements(project, "components/" + allUxComponent.name() + ".html.twig"));
}
}

return psiFiles;
}

@NotNull
public static Collection<PhpClass> getComponentClassesForTemplateFile(@NotNull Project project, @NotNull PsiFile psiFile) {
Collection<PhpClass> phpClasses = new HashSet<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,47 @@ public void testGetBlockLookupElements() {
assertNotNull(lookupElements.stream().filter(lookupElement -> "foobar".equals(lookupElement.getLookupString())).findFirst().orElse(null));
}

public void testGetBlockExtendsScopeInsideEmbed() {
PsiElement insideEmbed = TwigElementFactory.createPsiElement(getProject(), "" +
"{% block body %}\n" +
" {% embed \"test.html.twig\" %}\n" +
" {% block my_foobar %}" +
" {% macro foo %}{% endmacro %}\n" +
" {% endblock %}\n" +
" {% endembed %}\n" +
"{% endblock body %}\n", TwigElementTypes.MACRO_TAG);

TwigCompositeElement blockExtendsScope = (TwigCompositeElement) TwigUtil.getBlockExtendsScope(insideEmbed);
assertTrue(blockExtendsScope.getText().startsWith("{% embed"));
}

public void testGetBlockExtendsScopeInsideComponent() {
PsiElement insideEmbed = TwigElementFactory.createPsiElement(getProject(), "" +
"{% block body %}\n" +
" {% component DataTable with {headers: ['key', 'value'], data: [[1, 2], [3, 4]]} %}\n" +
" {% block my_foobar %}" +
" {% macro foo %}{% endmacro %}\n" +
" {% endblock %}\n" +
" {% endcomponent %}\n" +
"{% endblock body %}\n", TwigElementTypes.MACRO_TAG);

TwigCompositeElement blockExtendsScope = (TwigCompositeElement) TwigUtil.getBlockExtendsScope(insideEmbed);
assertTrue(blockExtendsScope.getText().startsWith("{% component"));
}

public void testFindScopedFile() {
PsiElement insideEmbed = TwigElementFactory.createPsiElement(getProject(), "" +
"{% block body %}\n" +
" {% component DataTable with {headers: ['key', 'value'], data: [[1, 2], [3, 4]]} %}\n" +
" {% block my_foobar %}" +
" {% macro foo %}{% endmacro %}\n" +
" {% endblock %}\n" +
" {% endcomponent %}\n" +
"{% endblock body %}\n", TwigElementTypes.MACRO_TAG);

TwigUtil.findScopedFile(insideEmbed);
}

private void assertEqual(Collection<String> c, String... values) {
if(!StringUtils.join(c, ",").equals(StringUtils.join(Arrays.asList(values), ","))) {
fail(String.format("Fail that '%s' is equal '%s'", StringUtils.join(c, ","), StringUtils.join(Arrays.asList(values), ",")));
Expand Down

0 comments on commit eb2d5c6

Please sign in to comment.