Skip to content

Commit 1f8dd00

Browse files
committed
Adding a linemarker to php route config
1 parent 63ffa89 commit 1f8dd00

File tree

4 files changed

+136
-0
lines changed

4 files changed

+136
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package fr.adrienbrault.idea.symfony2plugin.routing;
2+
3+
import com.intellij.codeInsight.daemon.LineMarkerInfo;
4+
import com.intellij.codeInsight.daemon.LineMarkerProvider;
5+
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo;
6+
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
7+
import com.intellij.psi.PsiElement;
8+
import com.intellij.psi.PsiFile;
9+
import com.jetbrains.php.lang.psi.PhpFile;
10+
import com.jetbrains.php.lang.psi.elements.*;
11+
import fr.adrienbrault.idea.symfony2plugin.Symfony2Icons;
12+
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
13+
import fr.adrienbrault.idea.symfony2plugin.util.resource.FileResourceUtil;
14+
import org.jetbrains.annotations.NotNull;
15+
import org.jetbrains.annotations.Nullable;
16+
17+
import java.util.Collection;
18+
import java.util.List;
19+
20+
/**
21+
* @author Daniel Espendiller <daniel@espendiller.net>
22+
*/
23+
public class PhpLineMarkerProvider implements LineMarkerProvider {
24+
@Nullable
25+
@Override
26+
public LineMarkerInfo<?> getLineMarkerInfo(@NotNull PsiElement psiElement) {
27+
return null;
28+
}
29+
30+
@Override
31+
public void collectSlowLineMarkers(@NotNull List<? extends PsiElement> psiElements, @NotNull Collection<? super LineMarkerInfo<?>> lineMarkerInfos) {
32+
if(psiElements.size() == 0 || !Symfony2ProjectComponent.isEnabled(psiElements.get(0))) {
33+
return;
34+
}
35+
36+
for(PsiElement psiElement : psiElements) {
37+
attachRouteActions(lineMarkerInfos, psiElement);
38+
39+
if(psiElement instanceof PhpFile) {
40+
RelatedItemLineMarkerInfo<PsiElement> lineMarker = FileResourceUtil.getFileImplementsLineMarker((PsiFile) psiElement);
41+
if(lineMarker != null) {
42+
lineMarkerInfos.add(lineMarker);
43+
}
44+
}
45+
}
46+
}
47+
48+
private void attachRouteActions(@NotNull Collection<? super LineMarkerInfo<?>> lineMarkerInfos, @NotNull PsiElement psiElement) {
49+
if (!(psiElement instanceof FunctionReference)) {
50+
return;
51+
}
52+
53+
MethodReference methodCall = (MethodReference) psiElement;
54+
String controllerMethod = RouteHelper.getPhpController(methodCall);
55+
56+
PsiElement[] methods = RouteHelper.getMethodsOnControllerShortcut(psiElement.getProject(), controllerMethod);
57+
if(methods.length > 0) {
58+
NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Symfony2Icons.TWIG_CONTROLLER_LINE_MARKER).
59+
setTargets(methods).
60+
setTooltipText("Navigate to action");
61+
62+
lineMarkerInfos.add(builder.createLineMarkerInfo(methodCall.getParameters()[0].getFirstChild()));
63+
}
64+
}
65+
}

src/main/java/fr/adrienbrault/idea/symfony2plugin/routing/RouteHelper.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,34 @@ public static String getYamlController(@NotNull YAMLKeyValue psiElement) {
835835
return null;
836836
}
837837

838+
/**
839+
* Find controller definition in php function call.
840+
* $routes->controller('FooController:method');
841+
*/
842+
@Nullable
843+
public static String getPhpController(@Nullable MethodReference methodCall) {
844+
if (methodCall == null || !methodCall.getName().equals("controller")) {
845+
return null;
846+
}
847+
848+
PhpExpression expression = methodCall;
849+
while(expression instanceof MethodReference) {
850+
expression = (PhpExpression) expression.getFirstChild();
851+
}
852+
853+
var expr = expression.getInferredType();
854+
855+
if (!"\\Symfony\\Component\\Routing\\Loader\\Configurator\\RoutingConfigurator".equals(expr.toString())) {
856+
return null;
857+
}
858+
859+
PsiElement parameter = methodCall.getParameters()[0];
860+
if (parameter instanceof StringLiteralExpression) {
861+
return ((StringLiteralExpression) parameter).getContents();
862+
}
863+
return null;
864+
}
865+
838866
@Nullable
839867
public static PsiElement getXmlRouteNameTarget(@NotNull XmlFile psiFile,@NotNull String routeName) {
840868

src/main/resources/META-INF/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@
227227
<codeInsight.lineMarkerProvider language="Twig" implementationClass="fr.adrienbrault.idea.symfony2plugin.templating.TwigLineMarkerProvider"/>
228228
<codeInsight.lineMarkerProvider language="yaml" implementationClass="fr.adrienbrault.idea.symfony2plugin.routing.YamlLineMarkerProvider"/>
229229
<codeInsight.lineMarkerProvider language="XML" implementationClass="fr.adrienbrault.idea.symfony2plugin.routing.XmlLineMarkerProvider"/>
230+
<codeInsight.lineMarkerProvider language="PHP" implementationClass="fr.adrienbrault.idea.symfony2plugin.routing.PhpLineMarkerProvider"/>
230231
<codeInsight.lineMarkerProvider language="XML" implementationClass="fr.adrienbrault.idea.symfony2plugin.dic.linemarker.XmlLineMarkerProvider"/>
231232
<codeInsight.lineMarkerProvider language="yaml" implementationClass="fr.adrienbrault.idea.symfony2plugin.dic.linemarker.YamlLineMarkerProvider"/>
232233
<codeInsight.lineMarkerProvider language="yaml" implementationClass="fr.adrienbrault.idea.symfony2plugin.config.ConfigLineMarkerProvider"/>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package fr.adrienbrault.idea.symfony2plugin.tests.routing;
2+
3+
import com.intellij.patterns.XmlPatterns;
4+
import com.intellij.psi.PsiFile;
5+
import com.jetbrains.php.lang.PhpFileType;
6+
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
7+
8+
/**
9+
* @author Daniel Espendiller <daniel@espendiller.net>
10+
*
11+
* @see fr.adrienbrault.idea.symfony2plugin.routing.PhpLineMarkerProvider
12+
*/
13+
public class PhpLineMarkerProviderTest extends SymfonyLightCodeInsightFixtureTestCase {
14+
15+
public void setUp() throws Exception {
16+
super.setUp();
17+
18+
myFixture.copyFileToProject("BundleScopeLineMarkerProvider.php");
19+
myFixture.copyFileToProject("XmlLineMarkerProvider.php");
20+
}
21+
22+
protected String getTestDataPath() {
23+
return "src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/routing/fixtures";
24+
}
25+
26+
public void testThatRouteLineMarkerForControllerIsGiven() {
27+
assertLineMarker(
28+
myFixture.configureByText(
29+
PhpFileType.INSTANCE,
30+
"<?php\n" +
31+
"use Symfony\\Component\\Routing\\Loader\\Configurator\\RoutingConfigurator;\n" +
32+
"\n" +
33+
"return function(RoutingConfigurator $routes) {\n" +
34+
" $routes->add('xml_route', '/xml')\n" +
35+
" ->controller('Foo\\\\Bar')\n" +
36+
" ;\n" +
37+
"};"
38+
),
39+
new LineMarker.ToolTipEqualsAssert("Navigate to action")
40+
);
41+
}
42+
}

0 commit comments

Comments
 (0)