Skip to content

Commit cda1f61

Browse files
committed
Named arguments should be clickable #1240
1 parent 6199db8 commit cda1f61

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

src/main/java/fr/adrienbrault/idea/symfony2plugin/config/yaml/YamlGoToDeclarationHandler.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.intellij.psi.tree.IElementType;
1212
import com.jetbrains.php.PhpIndex;
1313
import com.jetbrains.php.lang.psi.elements.Method;
14+
import com.jetbrains.php.lang.psi.elements.Parameter;
1415
import com.jetbrains.php.lang.psi.elements.PhpClass;
1516
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
1617
import fr.adrienbrault.idea.symfony2plugin.config.EventDispatcherSubscriberUtil;
@@ -88,6 +89,14 @@ public PsiElement[] getGotoDeclarationTargets(PsiElement psiElement, int i, Edit
8889
}
8990
}
9091

92+
if (elementType == YAMLTokenTypes.SCALAR_KEY) {
93+
String psiText = PsiElementUtils.getText(psiElement);
94+
95+
if(psiText.startsWith("$")) {
96+
targets.addAll(namedArgumentGoto(psiElement)) ;
97+
}
98+
}
99+
91100
// yaml Plugin BC: "!php/const:" is a tag
92101
if(elementType == YAMLTokenTypes.TAG) {
93102
String psiText = PsiElementUtils.getText(psiElement);
@@ -167,6 +176,17 @@ public PsiElement[] getGotoDeclarationTargets(PsiElement psiElement, int i, Edit
167176
return targets.toArray(new PsiElement[targets.size()]);
168177
}
169178

179+
private Collection<? extends PsiElement> namedArgumentGoto(PsiElement psiElement) {
180+
Collection<PsiElement> psiElements = new HashSet<>();
181+
182+
Parameter yamlNamedArgument = ServiceContainerUtil.getYamlNamedArgument(psiElement, new ContainerCollectionResolver.LazyServiceCollector(psiElement.getProject()));
183+
if (yamlNamedArgument != null) {
184+
psiElements.add(yamlNamedArgument);
185+
}
186+
187+
return psiElements;
188+
}
189+
170190
private boolean hasNewConst(@NotNull PsiElement psiElement) {
171191
PsiElement prevSibling = psiElement.getPrevSibling();
172192
while (prevSibling != null) {

src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/container/util/ServiceContainerUtil.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.jetbrains.php.PhpIndex;
1313
import com.jetbrains.php.lang.psi.elements.Field;
1414
import com.jetbrains.php.lang.psi.elements.Method;
15+
import com.jetbrains.php.lang.psi.elements.Parameter;
1516
import com.jetbrains.php.lang.psi.elements.PhpClass;
1617
import fr.adrienbrault.idea.symfony2plugin.config.xml.XmlHelper;
1718
import fr.adrienbrault.idea.symfony2plugin.dic.attribute.value.AttributeValueInterface;
@@ -366,6 +367,42 @@ public static ServiceTypeHint getYamlConstructorTypeHint(@NotNull YAMLScalar yam
366367
return null;
367368
}
368369

370+
/**
371+
* arguments: ['$foobar': '@foo']
372+
*/
373+
@Nullable
374+
public static Parameter getYamlNamedArgument(@NotNull PsiElement psiElement, @NotNull ContainerCollectionResolver.LazyServiceCollector lazyServiceCollector) {
375+
PsiElement context = psiElement.getContext();
376+
if(context instanceof YAMLKeyValue) {
377+
// arguments: ['$foobar': '@foo']
378+
379+
String parameterName = ((YAMLKeyValue) context).getKeyText();
380+
if(parameterName.startsWith("$") && parameterName.length() > 1) {
381+
PsiElement yamlMapping = context.getParent();
382+
if(yamlMapping instanceof YAMLMapping) {
383+
PsiElement yamlKeyValue = yamlMapping.getParent();
384+
if(yamlKeyValue instanceof YAMLKeyValue) {
385+
String keyText = ((YAMLKeyValue) yamlKeyValue).getKeyText();
386+
if(keyText.equals("arguments")) {
387+
YAMLMapping parentMapping = ((YAMLKeyValue) yamlKeyValue).getParentMapping();
388+
if(parentMapping != null) {
389+
String serviceId = getServiceClassFromServiceMapping(parentMapping);
390+
if(StringUtils.isNotBlank(serviceId)) {
391+
PhpClass serviceClass = ServiceUtil.getResolvedClassDefinition(psiElement.getProject(), serviceId, lazyServiceCollector);
392+
if(serviceClass != null) {
393+
return PhpElementsUtil.getConstructorParameterArgumentByName(serviceClass, StringUtils.stripStart(parameterName, "$"));
394+
}
395+
}
396+
}
397+
}
398+
}
399+
}
400+
}
401+
}
402+
403+
return null;
404+
}
405+
369406
/**
370407
* Symfony 3.3: "class" is optional; use service name for its it
371408
*

src/main/java/fr/adrienbrault/idea/symfony2plugin/util/PhpElementsUtil.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,21 @@ public static Collection<String> getTernaryExpressionConditionStrings(@NotNull T
12991299
return types;
13001300
}
13011301

1302+
/**
1303+
* Find argument by name in constructor parameter: __construct($foobar)
1304+
*/
1305+
@Nullable
1306+
public static Parameter getConstructorParameterArgumentByName(@NotNull PhpClass phpClass, @NotNull String argumentName) {
1307+
Method constructor = phpClass.getConstructor();
1308+
if(constructor == null) {
1309+
return null;
1310+
}
1311+
1312+
return Arrays.stream(constructor.getParameters()).filter(
1313+
parameter -> argumentName.equals(parameter.getName())
1314+
).findFirst().orElse(null);
1315+
}
1316+
13021317
/**
13031318
* Find argument by name in constructor parameter: __construct($foobar)
13041319
*/

src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/config/yaml/YamlGoToDeclarationHandlerTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.intellij.patterns.PsiElementPattern;
55
import com.jetbrains.php.lang.PhpFileType;
66
import com.jetbrains.php.lang.psi.elements.Method;
7+
import com.jetbrains.php.lang.psi.elements.Parameter;
78
import com.jetbrains.php.lang.psi.elements.PhpClass;
89
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
910
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
@@ -226,6 +227,16 @@ public void testThatNavigationForControllerInvokeMethodIsAvailable() {
226227
);
227228
}
228229

230+
public void testNamedArgumentsNavigationForService() {
231+
assertNavigationMatch("services.yml", "" +
232+
"services:\n" +
233+
" Foo\\Bar:\n" +
234+
" arguments:\n" +
235+
" $<caret>i: ~\n",
236+
PlatformPatterns.psiElement(Parameter.class)
237+
);
238+
}
239+
229240
@NotNull
230241
private PsiElementPattern.Capture<PhpClass> getClassPattern() {
231242
return PlatformPatterns.psiElement(PhpClass.class);

0 commit comments

Comments
 (0)