Skip to content

Commit 6cc9104

Browse files
authored
Merge pull request #1933 from Haehnchen/feature/command-search
support latest command name extraction logic also in search everywhere
2 parents 78e99b8 + 4f2e901 commit 6cc9104

File tree

8 files changed

+106
-71
lines changed

8 files changed

+106
-71
lines changed

src/main/java/fr/adrienbrault/idea/symfony2plugin/action/SymfonySymbolSearchAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ public void processElementsWithName(@NotNull String name, @NotNull Processor<? s
242242

243243
for (SymfonyCommand symfonyCommand : SymfonyCommandUtil.getCommands(project)) {
244244
if(symfonyCommand.getName().equals(name)) {
245-
processor.process(new NavigationItemEx(symfonyCommand.getPsiElement(), name, Symfony2Icons.SYMFONY, "Command"));
245+
processor.process(new NavigationItemEx(symfonyCommand.getPhpClass(), name, Symfony2Icons.SYMFONY, "Command"));
246246
}
247247
}
248248

src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/command/SymfonyCommandTestRunLineMarkerProvider.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,14 @@
77
import com.intellij.icons.AllIcons;
88
import com.intellij.openapi.actionSystem.AnAction;
99
import com.intellij.psi.PsiElement;
10+
import com.intellij.psi.util.PsiTreeUtil;
1011
import com.intellij.util.ObjectUtils;
1112
import com.jetbrains.php.lang.lexer.PhpTokenTypes;
1213
import com.jetbrains.php.lang.psi.PhpPsiUtil;
13-
import com.jetbrains.php.lang.psi.elements.Field;
14-
import com.jetbrains.php.lang.psi.elements.PhpAttribute;
15-
import com.jetbrains.php.lang.psi.elements.PhpClass;
16-
import com.jetbrains.php.lang.psi.elements.PhpNamedElement;
14+
import com.jetbrains.php.lang.psi.elements.*;
1715
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
1816
import fr.adrienbrault.idea.symfony2plugin.util.PhpPsiAttributesUtil;
17+
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
1918
import org.jetbrains.annotations.NotNull;
2019
import org.jetbrains.annotations.Nullable;
2120

@@ -76,6 +75,32 @@ public static String getCommandNameFromClass(@NotNull PhpClass phpClass) {
7675

7776
// @TODO: provide tag resolving here
7877
// - { name: 'console.command', command: 'app:sunshine' }
78+
79+
// old style
80+
Method method = phpClass.findOwnMethodByName("configure");
81+
if(method != null) {
82+
PsiElement[] psiElements = PsiTreeUtil.collectElements(method, psiElement ->
83+
psiElement instanceof MethodReference && "setName".equals(((MethodReference) psiElement).getName())
84+
);
85+
86+
for (PsiElement psiElement : psiElements) {
87+
if(!(psiElement instanceof MethodReference)) {
88+
continue;
89+
}
90+
91+
PsiElement psiMethodParameter = PsiElementUtils.getMethodParameterPsiElementAt((MethodReference) psiElement, 0);
92+
if(psiMethodParameter == null) {
93+
continue;
94+
}
95+
96+
String stringValue = PhpElementsUtil.getStringValue(psiMethodParameter);
97+
if(stringValue == null) {
98+
continue;
99+
}
100+
101+
return stringValue;
102+
}
103+
}
79104
}
80105

81106
return null;

src/main/java/fr/adrienbrault/idea/symfony2plugin/navigation/SymfonyCommandSymbolContributor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public NavigationItem[] getItemsByName(String name, String s2, Project project,
4646

4747
for (SymfonyCommand symfonyCommand : SymfonyCommandUtil.getCommands(project)) {
4848
if(symfonyCommand.getName().equals(name)) {
49-
navigationItems.add(new NavigationItemEx(symfonyCommand.getPsiElement(), name, Symfony2Icons.SYMFONY, "Command"));
49+
navigationItems.add(new NavigationItemEx(symfonyCommand.getPhpClass(), name, Symfony2Icons.SYMFONY, "Command"));
5050
}
5151
}
5252

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,62 @@
11
package fr.adrienbrault.idea.symfony2plugin.util;
22

33
import com.intellij.openapi.project.Project;
4-
import com.intellij.psi.PsiElement;
5-
import com.intellij.psi.util.PsiTreeUtil;
4+
import com.intellij.openapi.util.Key;
5+
import com.intellij.psi.util.CachedValue;
6+
import com.intellij.psi.util.CachedValueProvider;
7+
import com.intellij.psi.util.CachedValuesManager;
8+
import com.intellij.psi.util.PsiModificationTracker;
69
import com.jetbrains.php.PhpIndex;
7-
import com.jetbrains.php.lang.psi.elements.Method;
8-
import com.jetbrains.php.lang.psi.elements.MethodReference;
910
import com.jetbrains.php.lang.psi.elements.PhpClass;
11+
import fr.adrienbrault.idea.symfony2plugin.dic.command.SymfonyCommandTestRunLineMarkerProvider;
1012
import fr.adrienbrault.idea.symfony2plugin.util.dict.SymfonyCommand;
1113
import org.jetbrains.annotations.NotNull;
1214

1315
import java.util.ArrayList;
1416
import java.util.Collection;
17+
import java.util.HashMap;
18+
import java.util.Map;
1519

1620
/**
1721
* @author Daniel Espendiller <daniel@espendiller.net>
1822
*/
1923
public class SymfonyCommandUtil {
24+
private static final Key<CachedValue<Map<String, String>>> SYMFONY_COMMAND_NAME_MAP = new Key<>("SYMFONY_COMMAND_NAME_MAP");
2025

2126
@NotNull
2227
public static Collection<SymfonyCommand> getCommands(@NotNull Project project) {
23-
24-
Collection<SymfonyCommand> symfonyCommands = new ArrayList<>();
25-
26-
for (PhpClass phpClass : PhpIndex.getInstance(project).getAllSubclasses("\\Symfony\\Component\\Console\\Command\\Command")) {
27-
28-
if(PhpElementsUtil.isTestClass(phpClass)) {
29-
continue;
30-
}
31-
32-
Method method = phpClass.findOwnMethodByName("configure");
33-
if(method == null) {
34-
continue;
35-
}
36-
37-
PsiElement[] psiElements = PsiTreeUtil.collectElements(method, psiElement ->
38-
psiElement instanceof MethodReference && "setName".equals(((MethodReference) psiElement).getName())
39-
);
40-
41-
for (PsiElement psiElement : psiElements) {
42-
43-
if(!(psiElement instanceof MethodReference)) {
44-
continue;
28+
Map<String, String> cachedValue = CachedValuesManager.getManager(project).getCachedValue(
29+
project,
30+
SYMFONY_COMMAND_NAME_MAP,
31+
() -> {
32+
Map<String, String> symfonyCommands = new HashMap<>();
33+
34+
for (PhpClass phpClass : PhpIndex.getInstance(project).getAllSubclasses("\\Symfony\\Component\\Console\\Command\\Command")) {
35+
if (PhpElementsUtil.isTestClass(phpClass)) {
36+
continue;
37+
}
38+
39+
String commandName = SymfonyCommandTestRunLineMarkerProvider.getCommandNameFromClass(phpClass);
40+
if (commandName != null) {
41+
symfonyCommands.put(commandName, phpClass.getFQN());
42+
}
4543
}
4644

47-
PsiElement psiMethodParameter = PsiElementUtils.getMethodParameterPsiElementAt((MethodReference) psiElement, 0);
48-
if(psiMethodParameter == null) {
49-
continue;
50-
}
45+
return CachedValueProvider.Result.create(symfonyCommands, PsiModificationTracker.MODIFICATION_COUNT);
46+
},
47+
false
48+
);
5149

52-
String stringValue = PhpElementsUtil.getStringValue(psiMethodParameter);
53-
if(stringValue == null) {
54-
continue;
55-
}
56-
57-
symfonyCommands.add(new SymfonyCommand(stringValue, psiElement));
50+
Collection<SymfonyCommand> symfonyCommands = new ArrayList<>();
51+
for (Map.Entry<String, String> entry : cachedValue.entrySet()) {
52+
Collection<PhpClass> anyByFQN = PhpIndex.getInstance(project).getAnyByFQN(entry.getValue());
53+
if (anyByFQN.isEmpty()) {
54+
continue;
5855
}
5956

57+
symfonyCommands.add(new SymfonyCommand(entry.getKey(), anyByFQN.iterator().next()));
6058
}
6159

6260
return symfonyCommands;
6361
}
64-
6562
}
Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
package fr.adrienbrault.idea.symfony2plugin.util.dict;
22

3-
import com.intellij.psi.PsiElement;
3+
import com.jetbrains.php.lang.psi.elements.PhpClass;
44
import org.jetbrains.annotations.NotNull;
55

66
/**
77
* @author Daniel Espendiller <daniel@espendiller.net>
88
*/
99
public class SymfonyCommand {
10-
1110
@NotNull
1211
private final String name;
1312

1413
@NotNull
15-
private final PsiElement psiElement;
14+
private final PhpClass phpClass;
1615

17-
public SymfonyCommand(@NotNull String name, @NotNull PsiElement psiElement) {
16+
public SymfonyCommand(@NotNull String name, @NotNull PhpClass phpClass) {
1817
this.name = name;
19-
this.psiElement = psiElement;
18+
this.phpClass = phpClass;
2019
}
2120

2221
@NotNull
@@ -25,8 +24,7 @@ public String getName() {
2524
}
2625

2726
@NotNull
28-
public PsiElement getPsiElement() {
29-
return psiElement;
27+
public PhpClass getPhpClass() {
28+
return phpClass;
3029
}
31-
3230
}

src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/dic/command/SymfonyCommandTestRunLineMarkerProviderTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,18 @@ public void testCommandNameFromDefaultPhpPropertyAsDefault() {
5757

5858
assertEquals("app:create-user", SymfonyCommandTestRunLineMarkerProvider.getCommandNameFromClass(phpClass));
5959
}
60+
61+
public void testCommandNameFromSetName() {
62+
PhpClass phpClass = PhpPsiElementFactory.createFromText(getProject(), PhpClass.class, "<?php\n" +
63+
"class FoobarCommand extends \\Symfony\\Component\\Console\\Command\\Command\n" +
64+
"{\n" +
65+
" public function configure()\n" +
66+
" {\n" +
67+
" $this->setName('set-const-command');\n" +
68+
" }\n" +
69+
"}"
70+
);
71+
72+
assertEquals("set-const-command", SymfonyCommandTestRunLineMarkerProvider.getCommandNameFromClass(phpClass));
73+
}
6074
}
Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package fr.adrienbrault.idea.symfony2plugin.tests.util;
22

3-
import com.intellij.openapi.util.Condition;
4-
import com.intellij.util.containers.ContainerUtil;
53
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
64
import fr.adrienbrault.idea.symfony2plugin.util.SymfonyCommandUtil;
75
import fr.adrienbrault.idea.symfony2plugin.util.dict.SymfonyCommand;
86

7+
import java.util.Collection;
8+
99
/**
1010
* @author Daniel Espendiller <daniel@espendiller.net>
1111
*/
@@ -24,26 +24,15 @@ public String getTestDataPath() {
2424
* @see SymfonyCommandUtil#getCommands
2525
*/
2626
public void testGetCommands() {
27-
for (String s : new String[]{"foo", "property", "const"}) {
28-
SymfonyCommand command = ContainerUtil.find(SymfonyCommandUtil.getCommands(getProject()), new SymfonyCommandCondition(s));
29-
assertNotNull(command);
30-
assertNotNull(command.getName().equals(s));
31-
assertNotNull(command.getPsiElement());
32-
}
33-
34-
assertNull(ContainerUtil.find(SymfonyCommandUtil.getCommands(getProject()), new SymfonyCommandCondition("unknown")));
35-
}
36-
37-
private static class SymfonyCommandCondition implements Condition<SymfonyCommand> {
38-
private final String name;
27+
Collection<SymfonyCommand> commands = SymfonyCommandUtil.getCommands(getProject());
3928

40-
public SymfonyCommandCondition(String name) {
41-
this.name = name;
42-
}
29+
for (String s : new String[]{"foo", "property", "const", "app:create-user-1", "app:create-user-2", "app:create-user-3"}) {
30+
SymfonyCommand command = commands.stream()
31+
.filter(symfonyCommand -> s.equals(symfonyCommand.getName())).findFirst()
32+
.orElseThrow();
4333

44-
@Override
45-
public boolean value(SymfonyCommand symfonyCommand) {
46-
return symfonyCommand.getName().equals(name);
34+
assertNotNull(command);
35+
assertNotNull(command.getPhpClass());
4736
}
4837
}
4938
}

src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/util/fixtures/SymfonyCommandUtilTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ function setName($i) {}
1010

1111
namespace Foo
1212
{
13+
use Symfony\Component\Console\Attribute\AsCommand;
1314
use Symfony\Component\Console\Command\Command;
1415

1516
class FooCommand extends Command
@@ -39,4 +40,15 @@ public function configure()
3940
$this->setName(self::FOO);
4041
}
4142
}
43+
44+
#[AsCommand('app:create-user-1')]
45+
class FoobarCommand1 extends Command {}
46+
47+
#[AsCommand(name: 'app:create-user-2')]
48+
class FoobarCommand2 extends Command {}
49+
50+
class FoobarCommand3 extends Command
51+
{
52+
protected static $defaultName = 'app:create-user-3';
53+
}
4254
}

0 commit comments

Comments
 (0)