diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/container/util/ServiceContainerUtil.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/container/util/ServiceContainerUtil.java index 43a9d051b..43c72723c 100644 --- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/container/util/ServiceContainerUtil.java +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/container/util/ServiceContainerUtil.java @@ -70,6 +70,7 @@ public class ServiceContainerUtil { }; public static final String AUTOWIRE_ATTRIBUTE_CLASS = "\\Symfony\\Component\\DependencyInjection\\Attribute\\Autowire"; + public static final String TAGGET_ITERATOR_ATTRIBUTE_CLASS = "\\Symfony\\Component\\DependencyInjection\\Attribute\\TaggedIterator"; @NotNull public static Collection getServicesInFile(@NotNull PsiFile psiFile) { diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/registrar/DicGotoCompletionRegistrar.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/registrar/DicGotoCompletionRegistrar.java index 28a8e3696..e6149ed5d 100644 --- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/registrar/DicGotoCompletionRegistrar.java +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/registrar/DicGotoCompletionRegistrar.java @@ -3,6 +3,8 @@ import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.patterns.PlatformPatterns; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementResolveResult; +import com.intellij.psi.ResolveResult; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.php.lang.psi.elements.PhpAttribute; import com.jetbrains.php.lang.psi.elements.StringLiteralExpression; @@ -16,6 +18,7 @@ import fr.adrienbrault.idea.symfony2plugin.stubs.ContainerCollectionResolver; import fr.adrienbrault.idea.symfony2plugin.util.MethodMatcher; import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil; +import fr.adrienbrault.idea.symfony2plugin.util.completion.TagNameCompletionProvider; import fr.adrienbrault.idea.symfony2plugin.util.dict.ServiceUtil; import org.jetbrains.annotations.NotNull; @@ -82,10 +85,27 @@ public void register(@NotNull GotoCompletionRegistrarParameter registrar) { PhpAttribute phpAttribute = PsiTreeUtil.getParentOfType(context, PhpAttribute.class); if (phpAttribute != null) { - String fqn = phpAttribute.getFQN(); - if (fqn != null && PhpElementsUtil.isInstanceOf(psiElement.getProject(), fqn, ServiceContainerUtil.AUTOWIRE_ATTRIBUTE_CLASS)) { - return new ParameterContributor((StringLiteralExpression) context); - } + return new ParameterContributor((StringLiteralExpression) context); + } + + return null; + } + ); + + // #[TaggedIterator('app.handler')] iterable $handlers + registrar.register( + PlatformPatterns.or( + PhpElementsUtil.getFirstAttributeStringPattern(ServiceContainerUtil.TAGGET_ITERATOR_ATTRIBUTE_CLASS), + PhpElementsUtil.getAttributeNamedArgumentStringPattern(ServiceContainerUtil.TAGGET_ITERATOR_ATTRIBUTE_CLASS, "tag") + ), psiElement -> { + PsiElement context = psiElement.getContext(); + if (!(context instanceof StringLiteralExpression)) { + return null; + } + + PhpAttribute phpAttribute = PsiTreeUtil.getParentOfType(context, PhpAttribute.class); + if (phpAttribute != null) { + return new TaggedIteratorContributor((StringLiteralExpression) context); } return null; @@ -104,7 +124,7 @@ public ParameterContributor(StringLiteralExpression element) { public Collection getLookupElements() { Collection results = new ArrayList<>(); - for(Map.Entry entry: ContainerCollectionResolver.getParameters(getElement().getProject()).entrySet()) { + for (Map.Entry entry: ContainerCollectionResolver.getParameters(getElement().getProject()).entrySet()) { results.add(new ParameterLookupElement(entry.getValue())); } @@ -115,11 +135,34 @@ public Collection getLookupElements() { @Override public Collection getPsiTargets(PsiElement element) { String contents = GotoCompletionUtil.getStringLiteralValue(element); - if(contents == null) { + if (contents == null) { return Collections.emptyList(); } return ServiceUtil.getParameterDefinition(element.getProject(), contents); } } + + private static class TaggedIteratorContributor extends GotoCompletionProvider { + public TaggedIteratorContributor(StringLiteralExpression element) { + super(element); + } + + @NotNull + @Override + public Collection getLookupElements() { + return TagNameCompletionProvider.getTagLookupElements(getElement().getProject()); + } + + @NotNull + @Override + public Collection getPsiTargets(PsiElement element) { + String contents = GotoCompletionUtil.getStringLiteralValue(element); + if(contents == null) { + return Collections.emptyList(); + } + + return new ArrayList<>(ServiceUtil.getTaggedClasses(getElement().getProject(), contents)); + } + } } diff --git a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/dic/registrar/DicGotoCompletionRegistrarTest.java b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/dic/registrar/DicGotoCompletionRegistrarTest.java index 9e8b6b059..9144df1dc 100644 --- a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/dic/registrar/DicGotoCompletionRegistrarTest.java +++ b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/dic/registrar/DicGotoCompletionRegistrarTest.java @@ -3,7 +3,6 @@ import com.intellij.patterns.PlatformPatterns; import com.jetbrains.php.lang.PhpFileType; import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase; -import org.jetbrains.yaml.YAMLFileType; /** * @author Daniel Espendiller @@ -13,8 +12,7 @@ public class DicGotoCompletionRegistrarTest extends SymfonyLightCodeInsightFixtu public void setUp() throws Exception { super.setUp(); myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject("classes.php")); - myFixture.configureByText(YAMLFileType.YML, "parameters:\n foo: foo"); - + myFixture.copyFileToProject("services.yml"); } public String getTestDataPath() { @@ -132,4 +130,40 @@ public void testParameterContributorForNamedAttribute() { PlatformPatterns.psiElement() ); } + + public void testTagContributorForTaggedIterator() { + assertCompletionContains(PhpFileType.INSTANCE, "')] iterable $handlers\n" + + " ) {}\n" + + "}", + "yaml_type_tag" + ); + + assertCompletionContains(PhpFileType.INSTANCE, "')] iterable $handlers\n" + + " ) {}\n" + + "}", + "yaml_type_tag" + ); + + assertNavigationMatch(PhpFileType.INSTANCE, "ype_tag')] iterable $handlers\n" + + " ) {}\n" + + "}", + PlatformPatterns.psiElement() + ); + } } diff --git a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/dic/registrar/fixtures/classes.php b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/dic/registrar/fixtures/classes.php index e4995ea34..5935d12c2 100644 --- a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/dic/registrar/fixtures/classes.php +++ b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/dic/registrar/fixtures/classes.php @@ -24,6 +24,17 @@ public function __construct( string $expression = null, ) {} } + + class TaggedIterator + { + public function __construct( + public string $tag, + public ?string $indexAttribute = null, + public ?string $defaultIndexMethod = null, + public ?string $defaultPriorityMethod = null, + public string|array $exclude = [], + ) {} + } } namespace @@ -46,4 +57,10 @@ public function bar($parameter) { } } +namespace Foo +{ + class Bar + { + } +} diff --git a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/dic/registrar/fixtures/services.yml b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/dic/registrar/fixtures/services.yml new file mode 100644 index 000000000..dfaaf3774 --- /dev/null +++ b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/dic/registrar/fixtures/services.yml @@ -0,0 +1,7 @@ +parameters: + foo: foo + +services: + Foo\Bar: + tags: + - { name: yaml_type_tag }