Skip to content

Commit e6b5e53

Browse files
committed
html href tags of twig files provides completion for routes with custom insertHandler including parameter
1 parent 2042d71 commit e6b5e53

File tree

5 files changed

+133
-1
lines changed

5 files changed

+133
-1
lines changed

META-INF/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@
443443

444444
<completion.contributor language="XML" implementationClass="fr.adrienbrault.idea.symfony2plugin.config.xml.XmlCompletionContributor"/>
445445
<completion.contributor language="Twig" implementationClass="fr.adrienbrault.idea.symfony2plugin.templating.TwigTemplateCompletionContributor"/>
446+
<completion.contributor language="HTML" implementationClass="fr.adrienbrault.idea.symfony2plugin.templating.completion.TwigHtmlCompletionContributor"/>
446447
<completion.contributor language="yaml" implementationClass="fr.adrienbrault.idea.symfony2plugin.config.yaml.YamlCompletionContributor"/>
447448

448449
<annotator language="PHP" implementationClass="fr.adrienbrault.idea.symfony2plugin.templating.PhpTemplateAnnotator"/>

src/fr/adrienbrault/idea/symfony2plugin/routing/RouteLookupElement.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
package fr.adrienbrault.idea.symfony2plugin.routing;
22

3+
import com.intellij.codeInsight.completion.InsertHandler;
4+
import com.intellij.codeInsight.completion.InsertionContext;
35
import com.intellij.codeInsight.lookup.LookupElement;
46
import com.intellij.codeInsight.lookup.LookupElementPresentation;
57
import fr.adrienbrault.idea.symfony2plugin.Symfony2Icons;
8+
import fr.adrienbrault.idea.symfony2plugin.asset.dic.AssetEnum;
9+
import fr.adrienbrault.idea.symfony2plugin.util.dict.ResourceFileInsertHandler;
610
import org.jetbrains.annotations.NotNull;
711

812
/**
913
* @author Adrien Brault <adrien.brault@gmail.com>
14+
* @author Daniel Espendiller <daniel@espendiller.net>
1015
*/
11-
public class RouteLookupElement extends LookupElement {
16+
public class RouteLookupElement extends LookupElement {
1217

1318
final private Route route;
1419
private boolean isWeak = false;
20+
private InsertHandler<RouteLookupElement> insertHandler;
1521

1622
public RouteLookupElement(Route route) {
1723
this.route = route;
@@ -35,4 +41,20 @@ public void renderElement(LookupElementPresentation presentation) {
3541
presentation.setIcon(!this.isWeak ? Symfony2Icons.ROUTE : Symfony2Icons.ROUTE_WEAK);
3642
}
3743

44+
@Override
45+
public void handleInsert(InsertionContext context) {
46+
if(insertHandler != null) {
47+
insertHandler.handleInsert(context, this);
48+
}
49+
super.handleInsert(context);
50+
}
51+
52+
public void withInsertHandler(InsertHandler<RouteLookupElement> insertHandler) {
53+
this.insertHandler = insertHandler;
54+
}
55+
56+
public Route getRoute() {
57+
return route;
58+
}
59+
3860
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package fr.adrienbrault.idea.symfony2plugin.templating.completion;
2+
3+
import com.intellij.codeInsight.completion.*;
4+
import com.intellij.codeInsight.lookup.LookupElement;
5+
import com.intellij.util.ProcessingContext;
6+
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
7+
import fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper;
8+
import fr.adrienbrault.idea.symfony2plugin.routing.RouteLookupElement;
9+
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigHtmlCompletionUtil;
10+
import org.jetbrains.annotations.NotNull;
11+
12+
import java.util.List;
13+
14+
public class TwigHtmlCompletionContributor extends CompletionContributor {
15+
16+
public TwigHtmlCompletionContributor() {
17+
18+
// add completion for href and provide twig insert handler
19+
// <a href="#">#</a>
20+
// <a href="{{ path('', {'foo' : 'bar'}) }}">#</a>
21+
extend(CompletionType.BASIC, TwigHtmlCompletionUtil.getHrefAttributePattern(), new CompletionProvider<CompletionParameters>() {
22+
@Override
23+
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext processingContext, @NotNull CompletionResultSet resultSet) {
24+
25+
if(!Symfony2ProjectComponent.isEnabled(parameters.getPosition())) {
26+
return;
27+
}
28+
29+
List<LookupElement> routesLookupElements = RouteHelper.getRoutesLookupElements(parameters.getPosition().getProject());
30+
for(LookupElement element: routesLookupElements) {
31+
if(element instanceof RouteLookupElement) {
32+
((RouteLookupElement) element).withInsertHandler(TwigPathFunctionInsertHandler.getInstance());
33+
}
34+
}
35+
36+
resultSet.addAllElements(routesLookupElements);
37+
38+
}
39+
});
40+
41+
}
42+
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package fr.adrienbrault.idea.symfony2plugin.templating.completion;
2+
3+
import com.intellij.codeInsight.completion.InsertHandler;
4+
import com.intellij.codeInsight.completion.InsertionContext;
5+
import com.jetbrains.php.completion.insert.PhpInsertHandlerUtil;
6+
import fr.adrienbrault.idea.symfony2plugin.routing.RouteLookupElement;
7+
import org.apache.commons.lang.StringUtils;
8+
import org.jetbrains.annotations.NotNull;
9+
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import java.util.Set;
13+
14+
public class TwigPathFunctionInsertHandler implements InsertHandler<RouteLookupElement> {
15+
16+
private static final TwigPathFunctionInsertHandler instance = new TwigPathFunctionInsertHandler();
17+
18+
public void handleInsert(@NotNull InsertionContext context, @NotNull RouteLookupElement lookupElement) {
19+
context.getDocument().insertString(context.getStartOffset(), "{{ path('");
20+
21+
StringBuilder stringBuilder = new StringBuilder();
22+
stringBuilder.append("'");
23+
24+
Set<String> vars = lookupElement.getRoute().getVariables();
25+
if(vars.size() > 0) {
26+
List<String> items = new ArrayList<String>();
27+
for(String var: vars) {
28+
items.add(String.format("'%s': '%s'", var, "x"));
29+
}
30+
stringBuilder.append(", {");
31+
stringBuilder.append(StringUtils.join(items, ", "));
32+
stringBuilder.append("}");
33+
}
34+
35+
stringBuilder.append(") }}");
36+
PhpInsertHandlerUtil.insertStringAtCaret(context.getEditor(), stringBuilder.toString());
37+
}
38+
39+
public static TwigPathFunctionInsertHandler getInstance(){
40+
return instance;
41+
}
42+
43+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package fr.adrienbrault.idea.symfony2plugin.templating.util;
2+
3+
import com.intellij.patterns.PlatformPatterns;
4+
import com.intellij.patterns.PsiElementPattern;
5+
import com.intellij.patterns.XmlPatterns;
6+
import com.intellij.psi.PsiElement;
7+
8+
public class TwigHtmlCompletionUtil {
9+
10+
public static PsiElementPattern.Capture<PsiElement> getHrefAttributePattern() {
11+
return PlatformPatterns.psiElement()
12+
.withParent(
13+
XmlPatterns.xmlAttributeValue()
14+
.withParent(XmlPatterns.xmlAttribute("href")
15+
)
16+
).inFile(XmlPatterns.psiFile()
17+
.withName(XmlPatterns
18+
.string().endsWith(".twig")
19+
)
20+
);
21+
}
22+
23+
}

0 commit comments

Comments
 (0)