8000 fix "Navigate to action" on controller with __invoke doesn't work #986 · Koc/idea-php-symfony2-plugin@cfc948a · GitHub
[go: up one dir, main page]

Skip to content

Commit cfc948a

Browse files
committed
fix "Navigate to action" on controller with __invoke doesn't work Haehnchen#986
1 parent 7de35ea commit cfc948a

File tree

4 files changed

+136
-3
lines changed

4 files changed

+136
-3
lines changed

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

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.jetbrains.php.lang.psi.PhpFile;
2727
import com.jetbrains.php.lang.psi.PhpPsiUtil;
2828
import com.jetbrains.php.lang.psi.elements.*;
29+
import com.jetbrains.php.refactoring.PhpNameUtil;
2930
import de.espend.idea.php.annotation.dict.PhpDocCommentAnnotation;
3031
import de.espend.idea.php.annotation.dict.PhpDocTagAnnotation;
3132
import de.espend.idea.php.annotation.util.AnnotationUtil;
@@ -152,6 +153,7 @@ public static PsiElement[] getMethods(Project project, String routeName) {
152153
* FooBundle\Controller\BarController::fooBarAction
153154
* foo_service_bar:fooBar
154155
* AcmeDemoBundle:Demo:hello
156+
* FooBundle\Controller\BarController (__invoke)
155157
*
156158
* @param project current project
157159
* @param controllerName controller service, raw or compiled
@@ -201,6 +203,16 @@ public static PsiElement[] getMethodsOnControllerShortcut(@NotNull Project proje
201203
return new PsiElement[] {controllerServiceAction.getMethod()};
202204
}
203205

206+
} else if(PhpNameUtil.isValidNamespaceFullName(controllerName, true)) {
207+
// FooBundle\Controller\BarController (__invoke)
208+
Method invoke = PhpElementsUtil.getClassMethod(project, controllerName, "__invoke");
209+
if(invoke != null) {
210+
return new PsiElement[] {invoke};
211+
}
212+
213+
// class fallback
214+
Collection<PhpClass> phpClass = PhpElementsUtil.getClassesInterface(project, controllerName);
215+
return phpClass.toArray(new PsiElement[phpClass.size()]);
204216
}
205217

206218
return new PsiElement[0];
@@ -543,6 +555,10 @@ public static String convertMethodToRouteShortcutControllerName(@NotNull Method
543555
return null;
544556
}
545557

558+
if("__invoke".equals(method.getName())) {
559+
return StringUtils.stripStart(phpClass.getFQN(), "\\");
560+
}
561+
546562
String className = StringUtils.stripStart(phpClass.getFQN(), "\\");
547563
int bundlePos = className.lastIndexOf("Bundle\\");
548564
if(bundlePos == -1) {
@@ -554,8 +570,12 @@ public static String convertMethodToRouteShortcutControllerName(@NotNull Method
554570
return null;
555571
}
556572

557-
String name = method.getName();
558-
String methodName = name.substring(0, name.length() - "Action".length());
573+
String methodName = method.getName();
574+
575+
// strip method action => FoobarAction
576+
if(methodName.endsWith("Action")) {
577+
methodName = methodName.substring(0, methodName.length() - "Action".length());
578+
}
559579

560580
// try to to find relative class name
561581
String controllerClass = className.toLowerCase();
@@ -1000,9 +1020,16 @@ private static Map<String, Route> getAllRoutesProxy(@NotNull Project project) {
10001020
return routes;
10011021
}
10021022

1023+
/**
1024+
* Foobar/Bar => Foobar\Bar
1025+
* \\Foobar\Foobar => Foobar\Bar
1026+
*/
10031027
@NotNull
10041028
private static String normalizeRouteController(@NotNull String string) {
1005-
return string.replace("/", "\\");
1029+
string = string.replace("/", "\\");
1030+
string = StringUtils.stripStart(string,"\\");
1031+
1032+
return string;
10061033
}
10071034

10081035
/**

tests/fr/adrienbrault/idea/symfony2plugin/tests/config/yaml/YamlGoToKnownDeclarationHandlerTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package fr.adrienbrault.idea.symfony2plugin.tests.config.yaml;
22

33
import com.intellij.patterns.PlatformPatterns;
4+
import com.jetbrains.php.lang.PhpFileType;
5+
import com.jetbrains.php.lang.psi.elements.Method;
46
import com.jetbrains.php.lang.psi.elements.PhpClass;
57
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
68
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
@@ -93,4 +95,20 @@ public void testNavigateForCallsMethodIsProvided() {
9395
PlatformPatterns.psiElement(PhpClass.class)
9496
);
9597
}
98+
99+
public void testThatNavigationForControllerInvokeMethodIsAvailable() {
100+
myFixture.configureByText(PhpFileType.INSTANCE, "<?php\n" +
101+
"class Foobar\n" +
102+
"{\n" +
103+
" public function __invoke() {}\n" +
104+
"}\n"
105+
);
106+
107+
assertNavigationMatch("routing.yml", "" +
108+
"foobar:\n" +
109+
" defaults:\n" +
110+
" _controller: Foo<caret>bar\n",
111+
PlatformPatterns.psiElement(Method.class)
112+
);
113+
}
96114
}

tests/fr/adrienbrault/idea/symfony2plugin/tests/routing/RouteHelperTest.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.intellij.psi.PsiFileFactory;
88
import com.intellij.psi.xml.XmlFile;
99
import com.intellij.util.containers.ContainerUtil;
10+
import com.jetbrains.php.lang.PhpFileType;
1011
import com.jetbrains.php.lang.psi.PhpPsiElementFactory;
1112
import com.jetbrains.php.lang.psi.elements.Method;
1213
import com.jetbrains.php.lang.psi.elements.PhpClass;
@@ -269,6 +270,29 @@ public void testConvertMethodToRouteShortcutControllerName() {
269270
assertEquals("FooBarFooBundle:SubFolder\\Sub:foo", RouteHelper.convertMethodToRouteShortcutControllerName(fooAction));
270271
}
271272

273+
/**
274+
* @see fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper#convertMethodToRouteShortcutControllerName
275+
*/
276+
public void testConvertMethodToRouteShortcutControllerForInvoke()
277+
{
278+
myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject("GetRoutesOnControllerAction.php"));
279+
280+
PhpClass phpClass = PhpPsiElementFactory.createPhpPsiFromText(getProject(), PhpClass.class, "<?php\n" +
281+
"namespace FooBar\\FooBundle\\Controller" +
282+
"{\n" +
283+
" class FooBarController\n" +
284+
" {\n" +
285+
" function __invoke() {}\n" +
286+
" }\n" +
287+
"}"
288+
);
289+
290+
Method fooAction = phpClass.findMethodByName("__invoke");
291+
assertNotNull(fooAction);
292+
293+
assertEquals("FooBar\\FooBundle\\Controller\\FooBarController", RouteHelper.convertMethodToRouteShortcutControllerName(fooAction));
294+
}
295+
272296
/**
273297
* @see fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper#getRoutesOnControllerAction
274298
*/
@@ -341,6 +365,7 @@ public void testGetRouteNameTarget() {
341365
assertNotNull(element);
342366
assertTrue(element.getText().contains("my_car_foo_stuff_2"));
343367
}
368+
344369
/**
345370
* @see fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper#isServiceController
346371
*/
@@ -353,6 +378,45 @@ public void testIsServiceController() {
353378
assertFalse(RouteHelper.isServiceController("Foo:bar:foo"));
354379
}
355380

381+
/**
382+
* @see fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper#getMethodsOnControllerShortcut
383+
*/
384+
public void testGetMethodsOnControllerShortcutForControllerAsInvokeAction() {
385+
myFixture.configureByText(PhpFileType.INSTANCE, "<?php\n" +
386+
"namespace Foobar;\n" +
387+
"class Bar\n" +
388+
"{\n" +
389+
" public function __invoke() {}\n" +
390+
" public function barAction() {}\n" +
391+
" public function barAction() {}\n" +
392+
"}\n"
393+
);
394+
395+
PsiElement[] targets = RouteHelper.getMethodsOnControllerShortcut(getProject(), "Foobar\\Bar");
396+
assertEquals("__invoke", ((Method) targets[0]).getName());
397+
398+
targets = RouteHelper.getMethodsOnControllerShortcut(getProject(), "\\Foobar\\Bar");
399+
assertEquals("__invoke", ((Method) targets[0]).getName());
400+
401+
targets = RouteHelper.getMethodsOnControllerShortcut(getProject(), "Foobar\\Bar::barAction");
402+
assertEquals("barAction", ((Method) targets[0]).getName());
403+
}
404+
405+
/**
406+
* @see fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper#getMethodsOnControllerShortcut
407+
*/
408+
public void testGetMethodsOnControllerShortcutForControllerAsInvokeWithoutInvokeMethodFallbackToClass() {
409+
myFixture.configureByText(PhpFileType.INSTANCE, "<?php\n" +
410+
"namespace Foobar;\n" +
411+
"class Bar\n" +
412+
"{\n" +
413+
"}\n"
414+
);
415+
416+
PsiElement[] targets = RouteHelper.getMethodsOnControllerShortcut(getProject(), "Foobar\\Bar");
417+
assertEquals("Bar", ((PhpClass) targets[0]).getName());
418+
}
419+
356420
@NotNull
357421
private XmlFile createXmlFile(@NotNull String content) {
358422
return (XmlFile) PsiFileFactory.getInstance(getProject()).createFileFromText("DUMMY__." + XmlFileType.INSTANCE.getDefaultExtension(), XmlFileType.INSTANCE, content);

tests/fr/adrienbrault/idea/symfony2plugin/tests/stubs/indexes/RoutesStubIndexTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,28 @@ public void testRouteSlashesNormalized() {
9696
value -> "FooBundle:Foo\\Foo:index".equalsIgnoreCase(value.getController())
9797
);
9898
}
99+
100+
/**
101+
* @see fr.adrienbrault.idea.symfony2plugin.stubs.indexes.RoutesStubIndex#getIndexer()
102+
*/
103+
public void testControllerAsInvokeRoutingSupportsClassPatternForDefaults() {
104+
myFixture.configureByText(YAMLFileType.YML, "" +
105+
"controller_invoke:\n" +
106+
" pattern: /\n" +
107+
" defaults: { _controller: Foobar\\Foobar\\Foobar }" +
108+
"\n" +
109+
"controller_invoke_2:\n" +
110+
" pattern: /\n" +
111+
" defaults: { _controller: \\Foobar\\Foobar\\Foobar }" +
112+
"\n"
113+
);
114+
115+
assertIndexContainsKeyWithValue(RoutesStubIndex.KEY, "controller_invoke",
116+
value -> "Foobar\\Foobar\\Foobar".equalsIgnoreCase(value.getController())
117+
);
118+
119+
assertIndexContainsKeyWithValue(RoutesStubIndex.KEY, "controller_invoke_2",
120+
value -> "Foobar\\Foobar\\Foobar".equalsIgnoreCase(value.getController())
121+
);
122+
}
99123
}

0 commit comments

Comments
 (0)
0