5252import org .apache .commons .lang .StringUtils ;
5353import org .jetbrains .annotations .NotNull ;
5454import org .jetbrains .annotations .Nullable ;
55+ import org .jetbrains .yaml .YAMLTokenTypes ;
5556import org .jetbrains .yaml .psi .YAMLCompoundValue ;
5657import org .jetbrains .yaml .psi .YAMLKeyValue ;
58+ import org .jetbrains .yaml .psi .YAMLMapping ;
5759import org .jetbrains .yaml .psi .YAMLScalar ;
5860
5961import 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 ();
0 commit comments