Skip to content

Commit

Permalink
allow path navigation for templates #1076
Browse files Browse the repository at this point in the history
  • Loading branch information
Haehnchen committed Nov 11, 2017
1 parent e8e1ae8 commit ecba86d
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 12 deletions.
53 changes: 51 additions & 2 deletions src/fr/adrienbrault/idea/symfony2plugin/TwigHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -336,16 +336,65 @@ public static PsiFile[] getTemplatePsiElements(@NotNull Project project, @NotNul
String templatePath = StringUtils.strip(normalizedTemplateName.replace(":", "/").replace("//", "/"), "/");
addFileInsideTwigPath(project, templatePath, psiFiles, twigPath);
}

}

}

psiFiles.addAll(getTemplateOverwrites(project, normalizedTemplateName));

return psiFiles.toArray(new PsiFile[psiFiles.size()]);
}

/**
* Switch template target on caret offset "foo/bar.html.twig". Resolve template name or directory structure:
*
* "foo" "bar.html.twig"
*/
@NotNull
public static Collection<PsiElement> getTemplateTargetOnOffset(@NotNull Project project, @NotNull String templateName, int offset) {
String normalizedTemplateName = normalizeTemplateName(templateName);

Collection<VirtualFile> virtualFiles = new ArrayList<>();

for (TwigPath twigPath : getTwigNamespaces(project)) {
if(!twigPath.isEnabled()) {
continue;
}

if(normalizedTemplateName.startsWith("@")) {
} else if(normalizedTemplateName.startsWith(":")) {
} else {
// FooBundle::base.html.twig
// FooBundle:Bar:base.html.twig
if(twigPath.getNamespaceType() == TwigPathIndex.NamespaceType.BUNDLE) {
}

// form_div_layout.html.twig
if(twigPath.isGlobalNamespace() && twigPath.getNamespaceType() == TwigPathIndex.NamespaceType.ADD_PATH) {
int i = templateName.indexOf("/", offset);
if(i > 0) {
String substring = templateName.substring(0, i);

VirtualFile relativeFile = VfsUtil.findRelativeFile(twigPath.getDirectory(project), substring);
if(relativeFile != null) {
virtualFiles.add(relativeFile);
}
}
}

// Bundle overwrite:
// FooBundle:index.html -> app/views/FooBundle:index.html
if(twigPath.isGlobalNamespace() && !normalizedTemplateName.startsWith(":") && !normalizedTemplateName.startsWith("@")) {
}
}
}

return virtualFiles
.stream()
.map(virtualFile -> PsiManager.getInstance(project).findDirectory(virtualFile))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}

/**
* Resolve TwigFile to its possible template names:
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
Expand Down Expand Up @@ -36,7 +37,7 @@ public class TwigTemplateGoToDeclarationHandler implements GotoDeclarationHandle

@Nullable
@Override
public PsiElement[] getGotoDeclarationTargets(PsiElement psiElement, int i, Editor editor) {
public PsiElement[] getGotoDeclarationTargets(PsiElement psiElement, int offset, Editor editor) {

if(!Symfony2ProjectComponent.isEnabled(psiElement) || !PlatformPatterns.psiElement().withLanguage(TwigLanguage.INSTANCE).accepts(psiElement)) {
return null;
Expand All @@ -55,7 +56,8 @@ public PsiElement[] getGotoDeclarationTargets(PsiElement psiElement, int i, Edit

// support: {% include() %}, {{ include() }}
if(TwigHelper.getTemplateFileReferenceTagPattern().accepts(psiElement) || TwigHelper.getPrintBlockFunctionPattern("include", "source").accepts(psiElement)) {
return this.getTwigFiles(psiElement);
Collection<PsiElement> twigFiles = this.getTwigFiles(psiElement, offset);
return twigFiles.toArray(new PsiElement[twigFiles.size()]);
}

if(TwigHelper.getAutocompletableRoutePattern().accepts(psiElement)) {
Expand Down Expand Up @@ -85,7 +87,8 @@ public PsiElement[] getGotoDeclarationTargets(PsiElement psiElement, int i, Edit
if (PlatformPatterns.psiElement(TwigTokenTypes.STRING_TEXT)
.withText(PlatformPatterns.string().endsWith(".twig")).accepts(psiElement)) {

return this.getTwigFiles(psiElement);
Collection<PsiElement> twigFiles = this.getTwigFiles(psiElement, offset);
return twigFiles.toArray(new PsiElement[twigFiles.size()]);
}

if(TwigHelper.getPrintBlockOrTagFunctionPattern("controller").accepts(psiElement) || TwigHelper.getStringAfterTagNamePattern("render").accepts(psiElement)) {
Expand Down Expand Up @@ -173,15 +176,26 @@ private Collection<PsiElement> getControllerGoTo(@NotNull PsiElement psiElement
return Arrays.asList(RouteHelper.getMethodsOnControllerShortcut(psiElement.getProject(), text));
}

@Nullable
private PsiElement[] getTwigFiles(PsiElement psiElement) {

@NotNull
private Collection<PsiElement> getTwigFiles(@NotNull PsiElement psiElement, int offset) {
String templateName = psiElement.getText();
PsiElement[] psiElements = TwigHelper.getTemplatePsiElements(psiElement.getProject(), templateName);

if(psiElements.length == 0) {
return null;
}
Collection<PsiElement> psiElements = new ArrayList<>();

// files
psiElements.addAll(
Arrays.asList(TwigHelper.getTemplatePsiElements(psiElement.getProject(), templateName))
);

// directory
TextRange textRange = psiElement.getTextRange();

int startOffset = textRange.getStartOffset();
int myOffset = offset - startOffset;

psiElements.addAll(
TwigHelper.getTemplateTargetOnOffset(psiElement.getProject(), templateName, myOffset)
);

return psiElements;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package fr.adrienbrault.idea.symfony2plugin.tests;

import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import fr.adrienbrault.idea.symfony2plugin.Settings;
import fr.adrienbrault.idea.symfony2plugin.TwigHelper;
Expand Down Expand Up @@ -86,6 +87,17 @@ public void testGetTwigAndPhpTemplateFiles() {
);
}

/**
* @see fr.adrienbrault.idea.symfony2plugin.TwigHelper#getTwigAndPhpTemplateFiles
*/
public void testGetTemplateTargetOnOffset() {
createFiles("res/foobar/foo.html.twig");

Settings.getInstance(getProject()).twigNamespaces.addAll(createTwigNamespaceSettings());

assertTrue(TwigHelper.getTemplateTargetOnOffset(getProject(), "foobar/foo.html.twig", 3).stream().filter(psiElement -> psiElement instanceof PsiDirectory && "foobar".equals(((PsiDirectory) psiElement).getName())) .count() > 0);
}

@NotNull
private List<TwigNamespaceSetting> createTwigNamespaceSettings() {
return Arrays.asList(
Expand Down

0 comments on commit ecba86d

Please sign in to comment.