Skip to content

Commit 79f5e28

Browse files
committed
fix pattern for Yaml method "calls" #755 also implement named services support
1 parent 35617cc commit 79f5e28

File tree

8 files changed

+162
-69
lines changed

8 files changed

+162
-69
lines changed

src/fr/adrienbrault/idea/symfony2plugin/config/yaml/YamlCompletionContributor.java

+15-15
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.intellij.psi.PsiElement;
1212
import com.intellij.psi.PsiFile;
1313
import com.intellij.psi.util.PsiTreeUtil;
14+
import com.intellij.util.Consumer;
1415
import com.intellij.util.ProcessingContext;
1516
import com.jetbrains.php.completion.PhpLookupElement;
1617
import com.jetbrains.php.lang.psi.elements.Method;
@@ -199,9 +200,12 @@ public void addCompletions(@NotNull CompletionParameters parameters,
199200
YamlElementPatternHelper.getSingleLineScalarKey("alias")
200201
), new FormAliasCompletionProvider());
201202

202-
extend(CompletionType.BASIC, StandardPatterns.and(
203-
YamlElementPatternHelper.getInsideKeyValue("calls")
204-
), new ServiceCallsMethodCompletion());
203+
// - [ setContainer, [ @service_container ] ]
204+
extend(
205+
CompletionType.BASIC,
206+
YamlElementPatternHelper.getInsideKeyValue("calls"),
207+
new ServiceCallsMethodCompletion()
208+
);
205209

206210
extend(CompletionType.BASIC, StandardPatterns.and(
207211
YamlElementPatternHelper.getInsideKeyValue("tags"),
@@ -380,27 +384,23 @@ protected void addCompletions(@NotNull CompletionParameters completionParameters
380384
private class ServiceCallsMethodCompletion extends CompletionProvider<CompletionParameters> {
381385

382386
protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) {
383-
384387
if(!Symfony2ProjectComponent.isEnabled(completionParameters.getPosition())) {
385388
return;
386389
}
387390

388-
// TODO: move this to pattern; filters match on parameter array
389391
// - [ setContainer, [ @service_container ] ]
390392
PsiElement psiElement = completionParameters.getPosition();
391-
if(psiElement.getParent() == null || !(psiElement.getParent().getContext() instanceof YAMLSequence)) {
392-
return;
393-
}
394393

395-
YAMLKeyValue callYamlKeyValue = PsiTreeUtil.getParentOfType(psiElement, YAMLKeyValue.class);
396-
if(callYamlKeyValue == null) {
397-
return;
394+
PsiElement yamlScalar = psiElement.getParent();
395+
if(yamlScalar instanceof YAMLScalar) {
396+
YamlHelper.visitServiceCall((YAMLScalar) yamlScalar, clazz -> {
397+
PhpClass phpClass = ServiceUtil.getResolvedClassDefinition(psiElement.getProject(), clazz);
398+
if(phpClass != null) {
399+
PhpElementsUtil.addClassPublicMethodCompletion(completionResultSet, phpClass);
400+
}
401+
});
398402
}
399-
400-
addYamlClassMethods(callYamlKeyValue.getContext(), completionResultSet, "class");
401-
402403
}
403-
404404
}
405405

406406
private static void addYamlClassMethods(@Nullable PsiElement psiElement, CompletionResultSet completionResultSet, String classTag) {

src/fr/adrienbrault/idea/symfony2plugin/config/yaml/YamlGoToKnownDeclarationHandler.java

+12-23
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.intellij.psi.PsiElement;
99
import com.intellij.psi.PsiFile;
1010
import com.intellij.psi.util.PsiTreeUtil;
11+
import com.intellij.util.Consumer;
1112
import com.jetbrains.php.lang.psi.elements.Method;
1213
import com.jetbrains.php.lang.psi.elements.PhpClass;
1314
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
@@ -191,31 +192,19 @@ private void getClassGoto(PsiElement psiElement, List<PsiElement> results) {
191192
}
192193

193194
private void getMethodGoto(PsiElement psiElement, List<PsiElement> results) {
194-
195-
YAMLCompoundValue yamlCompoundValue = PsiTreeUtil.getParentOfType(psiElement, YAMLCompoundValue.class);
196-
if(yamlCompoundValue == null) {
197-
return;
198-
}
199-
200-
yamlCompoundValue = PsiTreeUtil.getParentOfType(yamlCompoundValue, YAMLCompoundValue.class);
201-
if(yamlCompoundValue == null) {
202-
return;
203-
}
204-
205-
YAMLKeyValue classKeyValue = PsiElementUtils.getChildrenOfType(yamlCompoundValue, PlatformPatterns.psiElement(YAMLKeyValue.class).withName("class"));
206-
if(classKeyValue == null) {
207-
return;
208-
}
209-
210-
PhpClass phpClass = ServiceUtil.getResolvedClassDefinition(psiElement.getProject(), classKeyValue.getValueText());
211-
if(phpClass != null) {
212-
for(Method method: PhpElementsUtil.getClassPublicMethod(phpClass)) {
213-
if(method.getName().equals(PsiElementUtils.trimQuote(psiElement.getText()))) {
214-
results.add(method);
195+
PsiElement parent = psiElement.getParent();
196+
if(parent instanceof YAMLScalar) {
197+
YamlHelper.visitServiceCall((YAMLScalar) parent, clazz -> {
198+
PhpClass phpClass = ServiceUtil.getResolvedClassDefinition(psiElement.getProject(),clazz);
199+
if(phpClass != null) {
200+
for(Method method: PhpElementsUtil.getClassPublicMethod(phpClass)) {
201+
if(method.getName().equals(PsiElementUtils.trimQuote(psiElement.getText()))) {
202+
results.add(method);
203+
}
204+
}
215205
}
216-
}
206+
});
217207
}
218-
219208
}
220209

221210
private void getTagMethodGoto(PsiElement psiElement, List<PsiElement> results) {

src/fr/adrienbrault/idea/symfony2plugin/config/yaml/inspection/EventMethodCallInspection.java

+8-31
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
1313
import com.intellij.psi.util.PsiTreeUtil;
1414
import com.intellij.psi.xml.XmlFile;
15+
import com.intellij.util.Consumer;
1516
import com.jetbrains.php.lang.parser.PhpElementTypes;
1617
import com.jetbrains.php.lang.psi.PhpFile;
1718
import com.jetbrains.php.lang.psi.elements.Method;
@@ -141,37 +142,14 @@ private void annotateCallMethod(@NotNull final PsiElement psiElement, @NotNull P
141142
}
142143

143144
private void visitYamlMethod(PsiElement psiElement, ProblemsHolder holder, ContainerCollectionResolver.LazyServiceCollector collector) {
144-
if(!YamlElementPatternHelper.getInsideKeyValue("calls").accepts(psiElement)){
145-
return;
146-
}
147-
148-
PsiElement parent = psiElement.getParent();
149-
if(!(parent instanceof YAMLScalar)) {
150-
return;
151-
}
152-
153-
PsiElement yamlSeq = parent.getContext();
154-
if(!(yamlSeq instanceof YAMLSequenceItem)) {
155-
return;
156-
}
157-
158-
PsiElement context = yamlSeq.getContext();
159-
if(!(context instanceof YAMLSequence)) {
160-
return;
161-
}
162-
163-
YAMLKeyValue callYamlKeyValue = PsiTreeUtil.getParentOfType(psiElement, YAMLKeyValue.class);
164-
if(callYamlKeyValue == null) {
165-
return;
166-
}
167-
168-
YAMLKeyValue classKeyValue = YamlHelper.getYamlKeyValue(callYamlKeyValue.getContext(), "class");
169-
if(classKeyValue == null) {
170-
return;
145+
if(YamlElementPatternHelper.getInsideKeyValue("calls").accepts(psiElement)) {
146+
PsiElement parent = psiElement.getParent();
147+
if ((parent instanceof YAMLScalar)) {
148+
YamlHelper.visitServiceCall((YAMLScalar) parent, s ->
149+
registerMethodProblem(psiElement, holder, YamlHelper.trimSpecialSyntaxServiceName(s), collector)
150+
);
151+
}
171152
}
172-
173-
registerMethodProblem(psiElement, holder, getServiceName(classKeyValue.getValue()), collector);
174-
175153
}
176154

177155
private void registerMethodProblem(final @NotNull PsiElement psiElement, @NotNull ProblemsHolder holder, @NotNull String classKeyValue, ContainerCollectionResolver.LazyServiceCollector collector) {
@@ -285,6 +263,5 @@ public void visitElement(PsiElement element) {
285263
}
286264
}
287265
}
288-
289266
}
290267
}

src/fr/adrienbrault/idea/symfony2plugin/util/yaml/YamlHelper.java

+49
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.intellij.util.ObjectUtils;
1515
import com.intellij.util.Processor;
1616
import com.intellij.util.containers.ContainerUtil;
17+
import com.jetbrains.php.refactoring.PhpNameUtil;
1718
import fr.adrienbrault.idea.symfony2plugin.dic.tags.yaml.StaticAttributeResolver;
1819
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
1920
import fr.adrienbrault.idea.symfony2plugin.util.yaml.visitor.YamlServiceTag;
@@ -923,4 +924,52 @@ public static boolean isClassServiceId(@NotNull String serviceId) {
923924

924925
return false;
925926
}
927+
928+
/**
929+
* service_name:
930+
* class: FOOBAR
931+
* calls:
932+
* - [onF<caret>oobar, []]
933+
*
934+
* FOOBAR:
935+
* calls:
936+
* - [onF<caret>oobar, []]
937+
*/
938+
public static void visitServiceCall(@NotNull YAMLScalar yamlScalar, @NotNull Consumer<String> consumer) {
939+
PsiElement yamlSeq = yamlScalar.getContext();
940+
if(yamlSeq instanceof YAMLSequenceItem) {
941+
PsiElement context = yamlSeq.getContext();
942+
if(context instanceof YAMLSequence) {
943+
PsiElement yamlSequenceItem = context.getParent();
944+
if(yamlSequenceItem instanceof YAMLSequenceItem) {
945+
PsiElement yamlSeq1 = yamlSequenceItem.getParent();
946+
if(yamlSeq1 instanceof YAMLSequence) {
947+
PsiElement callYamlKeyValue = yamlSeq1.getParent();
948+
if(callYamlKeyValue instanceof YAMLKeyValue) {
949+
YAMLKeyValue classKeyValue = YamlHelper.getYamlKeyValue(callYamlKeyValue.getContext(), "class");
950+
if(classKeyValue != null) {
951+
// "class" key found use this as valid class name
952+
String valueText = classKeyValue.getValueText();
953+
if(StringUtils.isNotBlank(valueText)) {
954+
consumer.consume(valueText);
955+
}
956+
} else {
957+
// named services; key is our class name
958+
PsiElement yamlMapping = callYamlKeyValue.getParent();
959+
if(yamlMapping instanceof YAMLMapping) {
960+
PsiElement parent = yamlMapping.getParent();
961+
if(parent instanceof YAMLKeyValue) {
962+
String keyText = ((YAMLKeyValue) parent).getKeyText();
963+
if(!keyText.contains(".") && PhpNameUtil.isValidNamespaceFullName(keyText)) {
964+
consumer.consume(keyText);
965+
}
966+
}
967+
}
968+
}
969+
}
970+
}
971+
}
972+
}
973+
}
974+
}
926975
}

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

+24
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package fr.adrienbrault.idea.symfony2plugin.tests.config.yaml;
22

3+
import com.intellij.patterns.PlatformPatterns;
34
import com.jetbrains.php.lang.PhpFileType;
5+
import com.jetbrains.php.lang.psi.elements.PhpClass;
46
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
7+
import org.jetbrains.yaml.YAMLFileType;
58

69
import java.io.File;
710

@@ -19,6 +22,7 @@ public void setUp() throws Exception {
1922
myFixture.configureByText("config_foo.yml", "");
2023
myFixture.configureByFile("YamlCompletionContributor.php");
2124
myFixture.configureByFile("tagged.services.xml");
25+
myFixture.configureByFile("classes.php");
2226
}
2327

2428
public String getTestDataPath() {
@@ -201,4 +205,24 @@ public void testParameterCompletionInsertHandler() {
201205
" foo: [\"%foo_parameter%\"]"
202206
);
203207
}
208+
209+
public void testThatMethodOfClassAreCompleted() {
210+
assertCompletionContains(YAMLFileType.YML, "" +
211+
"services:\n" +
212+
" foobar:\n" +
213+
" class: Foo\\Bar\n" +
214+
" calls:\n" +
215+
" - [ <caret> ]\n",
216+
"setBar"
217+
);
218+
219+
assertCompletionContains(YAMLFileType.YML, "" +
220+
"services:\n" +
221+
" foobar:\n" +
222+
" class: Foo\\Bar\n" +
223+
" calls:\n" +
224+
" - [ '<caret>' ]\n",
225+
"setBar"
226+
);
227+
}
204228
}

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

+11
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,15 @@ public void testNavigateToClassServiceAsKeyForSymfony33() {
8282
PlatformPatterns.psiElement(PhpClass.class)
8383
);
8484
}
85+
86+
public void testNavigateForCallsMethodIsProvided() {
87+
assertNavigationMatch("services.yml", "" +
88+
"services:\n" +
89+
" foobar:\n" +
90+
" class: Foo\\Bar\n" +
91+
" calls:\n" +
92+
" - [ set<caret>Bar, [@foo]]\n" +
93+
PlatformPatterns.psiElement(PhpClass.class)
94+
);
95+
}
8596
}

tests/fr/adrienbrault/idea/symfony2plugin/tests/config/yaml/fixtures/classes.php

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class MyDateTime
1212
class Bar
1313
{
1414
function __construct($i, $z) { }
15+
function setBar() {}
1516
}
1617

1718
class Apple

tests/fr/adrienbrault/idea/symfony2plugin/tests/util/yaml/YamlHelperLightTest.java

+42
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fr.adrienbrault.idea.symfony2plugin.tests.util.yaml;
22

33
import com.intellij.psi.PsiElement;
4+
import com.intellij.util.Consumer;
45
import com.intellij.util.Function;
56
import com.intellij.util.containers.ContainerUtil;
67
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
@@ -14,10 +15,12 @@
1415
import org.jetbrains.yaml.psi.YAMLCompoundValue;
1516
import org.jetbrains.yaml.psi.YAMLFile;
1617
import org.jetbrains.yaml.psi.YAMLKeyValue;
18+
import org.jetbrains.yaml.psi.YAMLScalar;
1719
import org.jetbrains.yaml.psi.impl.YAMLArrayImpl;
1820
import org.jetbrains.yaml.psi.impl.YAMLHashImpl;
1921

2022
import java.util.ArrayList;
23+
import java.util.Collection;
2124
import java.util.List;
2225
import java.util.Set;
2326

@@ -375,6 +378,45 @@ public void testInsertKeyValueWithMissingMainKeyInRoot() {
375378
);
376379
}
377380

381+
/**
382+
* @see fr.adrienbrault.idea.symfony2plugin.util.yaml.YamlHelper#visitServiceCall
383+
*/
384+
public void testVisitServiceCall() {
385+
myFixture.configureByText(YAMLFileType.YML, "services:\n" +
386+
" foobar:\n" +
387+
" class: Foo\\Bar\n" +
388+
" calls:\n" +
389+
" - [ '<caret>' ]\n"
390+
);
391+
392+
PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset());
393+
YAMLScalar parent = (YAMLScalar) psiElement.getParent();
394+
395+
Collection<String> values = new ArrayList<>();
396+
YamlHelper.visitServiceCall(parent, values::add);
397+
398+
assertContainsElements(values, "Foo\\Bar");
399+
}
400+
401+
/**
402+
* @see fr.adrienbrault.idea.symfony2plugin.util.yaml.YamlHelper#visitServiceCall
403+
*/
404+
public void testVisitServiceCallForNamedServices() {
405+
myFixture.configureByText(YAMLFileType.YML, "services:\n" +
406+
" Foo\\Bar:\n" +
407+
" calls:\n" +
408+
" - [ '<caret>' ]\n"
409+
);
410+
411+
PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset());
412+
YAMLScalar parent = (YAMLScalar) psiElement.getParent();
413+
414+
Collection<String> values = new ArrayList<>();
415+
YamlHelper.visitServiceCall(parent, values::add);
416+
417+
assertContainsElements(values, "Foo\\Bar");
418+
}
419+
378420
private static class ListYamlTagVisitor implements YamlTagVisitor {
379421

380422
private List<YamlServiceTag> items = new ArrayList<YamlServiceTag>();

0 commit comments

Comments
 (0)