Skip to content

Commit 4998b64

Browse files
authored
Merge pull request #1973 from Haehnchen/feature/bind-parameter-witch
namedargument completion can now reflect the "bind" or "service" scope
2 parents 63aecd6 + 619e244 commit 4998b64

File tree

5 files changed

+92
-6
lines changed

5 files changed

+92
-6
lines changed

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

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@
5252
import org.apache.commons.lang.StringUtils;
5353
import org.jetbrains.annotations.NotNull;
5454
import org.jetbrains.annotations.Nullable;
55+
import org.jetbrains.yaml.YAMLTokenTypes;
5556
import org.jetbrains.yaml.psi.YAMLCompoundValue;
5657
import org.jetbrains.yaml.psi.YAMLKeyValue;
58+
import org.jetbrains.yaml.psi.YAMLMapping;
5759
import org.jetbrains.yaml.psi.YAMLScalar;
5860

5961
import java.util.*;
@@ -265,6 +267,9 @@ public void addCompletions(@NotNull CompletionParameters parameters,
265267
// _defaults:
266268
// bind:
267269
// $<caret>: ''
270+
// service:
271+
// arguments:
272+
// $<caret>: ''
268273
extend(
269274
CompletionType.BASIC,
270275
YamlElementPatternHelper.getNamedDefaultBindPattern(),
@@ -408,16 +413,66 @@ protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull
408413
* _defaults:
409414
* bind:
410415
* $projectDir: '%kernel.project_dir%'
416+
* foobar:
417+
* arguments:
418+
* $projectDir: '%kernel.project_dir%'
411419
*/
412420
private static class NamedArgumentCompletionProvider extends CompletionProvider<CompletionParameters> {
413421
@Override
414422
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
415-
HashSet<String> uniqueParameters = new HashSet<>();
416-
417423
PsiElement position = parameters.getPosition();
418424
boolean hasEmptyNextElement = position.getNextSibling() == null;
419425

420-
ServiceContainerUtil.visitNamedArguments(position.getContainingFile(), pair -> {
426+
YAMLMapping serviceDefintion = null;
427+
428+
Collection<Pair<Parameter, Integer>> arguments = new ArrayList<>();
429+
430+
// depending on code complete state we already have a key or not
431+
// then decide if we are inside a "service" or "default bind" scope
432+
if (position.getNode().getElementType() == YAMLTokenTypes.SCALAR_KEY) {
433+
// "$name" key exists
434+
YAMLKeyValue parentOfType = PsiTreeUtil.getParentOfType(position, YAMLKeyValue.class);
435+
YAMLKeyValue parentOfType2 = PsiTreeUtil.getParentOfType(parentOfType, YAMLKeyValue.class);
436+
if (parentOfType2 == null) {
437+
return;
438+
}
439+
440+
String keyText2 = parentOfType2.getKeyText();
441+
if (!"bind".equals(keyText2)) {
442+
serviceDefintion = parentOfType2.getParentMapping();
443+
}
444+
} else {
445+
// "$" its just a text element
446+
YAMLKeyValue parentOfType = PsiTreeUtil.getParentOfType(position, YAMLKeyValue.class);
447+
if (parentOfType == null) {
448+
return;
449+
}
450+
451+
if (!"bind".equals(parentOfType.getKeyText())) {
452+
serviceDefintion = parentOfType.getParentMapping();
453+
}
454+
}
455+
456+
ContainerCollectionResolver.LazyServiceCollector lazyServiceCollector = new ContainerCollectionResolver.LazyServiceCollector(position.getProject());
457+
458+
// visit full file for arguments or current service scope
459+
if (serviceDefintion == null) {
460+
ServiceContainerUtil.visitNamedArguments(position.getContainingFile(), arguments::add);
461+
} else {
462+
@Nullable PhpClass yamlNamedArgumentPhpClass = ServiceContainerUtil.getServicePhpClassFromServiceMapping(serviceDefintion, lazyServiceCollector);
463+
if (yamlNamedArgumentPhpClass != null) {
464+
Method constructor = yamlNamedArgumentPhpClass.getConstructor();
465+
if (constructor != null) {
466+
Parameter @NotNull [] constructorParameters = constructor.getParameters();
467+
for (int i = 0; i < constructorParameters.length; i++) {
468+
arguments.add(Pair.create(constructorParameters[i], i));
469+
}
470+
}
471+
}
472+
}
473+
474+
Set<String> uniqueParameters = new HashSet<>();
475+
for (Pair<Parameter, Integer> pair : arguments) {
421476
Parameter parameter = pair.getFirst();
422477
String parameterName = parameter.getName();
423478
if (uniqueParameters.contains(parameterName)) {
@@ -445,7 +500,7 @@ protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull
445500

446501
if (!parameter.getType().getTypes().stream().allMatch(PhpType::isPrimitiveType)) {
447502
// $foobar: '@service'
448-
result.addAllElements(getServiceSuggestion(position, pair, parameterName, new ContainerCollectionResolver.LazyServiceCollector(position.getProject())));
503+
result.addAllElements(getServiceSuggestion(position, pair, parameterName, lazyServiceCollector));
449504
} else {
450505
String parameterNormalized = parameterName.toLowerCase(Locale.ROOT).replaceAll("[^a-z0-9]", "");
451506
if (parameterNormalized.length() > 5) {
@@ -457,9 +512,14 @@ protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull
457512
}
458513
}
459514
}
460-
});
515+
}
461516
}
462517

518+
/**
519+
* Matched service name on instance
520+
*
521+
* $foobar: '@service'
522+
*/
463523
@NotNull
464524
private Collection<LookupElement> getServiceSuggestion(@NotNull PsiElement position, @NotNull Pair<Parameter, Integer> pair, @NotNull String parameterName, @NotNull ContainerCollectionResolver.LazyServiceCollector lazyServiceCollector) {
465525
Parameter parameter = pair.getFirst();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -804,7 +804,7 @@ public static ElementPattern<PsiElement> getPhpConstPattern() {
804804
* arguments:
805805
* $<caret>
806806
*/
807-
static ElementPattern<PsiElement> getNamedDefaultBindPattern() {
807+
public static ElementPattern<PsiElement> getNamedDefaultBindPattern() {
808808
// "__defaults" key
809809
PsiElementPattern.Capture<YAMLMapping> defaultsKey = PlatformPatterns.psiElement(YAMLMapping.class).withParent(PlatformPatterns.psiElement(YAMLKeyValue.class).with(new PatternCondition<YAMLKeyValue>("KeyText") {
810810
@Override

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,17 @@ public static String getServiceClassFromServiceMapping(@NotNull YAMLMapping yaml
672672
return null;
673673
}
674674

675+
@Nullable
676+
public static PhpClass getServicePhpClassFromServiceMapping(@NotNull YAMLMapping yamlMapping, @NotNull ContainerCollectionResolver.LazyServiceCollector lazyServiceCollector) {
677+
String serviceId = getServiceClassFromServiceMapping(yamlMapping);
678+
if (StringUtils.isNotBlank(serviceId)) {
679+
return ServiceUtil.getResolvedClassDefinition(yamlMapping.getProject(), serviceId, lazyServiceCollector);
680+
}
681+
682+
return null;
683+
}
684+
685+
675686
/**
676687
* <services>
677688
* <service class="Foo\\Bar\\Car">

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,16 @@ public void testNamedArgumentCompletionForServiceArguments() {
333333
"$myDateTime: '@foo'"
334334
);
335335

336+
assertCompletionNotContains(YAMLFileType.YML, "" +
337+
"services:\n" +
338+
" Foo\\Bus: ~\n" +
339+
"\n" +
340+
" Foo\\Car:\n" +
341+
" arguments:\n" +
342+
" $<caret>\n",
343+
"$myBus"
344+
);
345+
336346
assertCompletionContains(YAMLFileType.YML, "" +
337347
"services:\n" +
338348
" Foo\\Car:\n" +

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,9 @@ function __construct(\string $projectDir, \string $foobarEnv, \MyDateTime $myDat
2626
{
2727
}
2828
}
29+
30+
class Bus
31+
{
32+
function __construct($myBus) { }
33+
}
2934
}

0 commit comments

Comments
 (0)