diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/security/IsGrantedAnnotationReferences.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/security/IsGrantedAnnotationReferences.java new file mode 100644 index 000000000..ff1091bcd --- /dev/null +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/security/IsGrantedAnnotationReferences.java @@ -0,0 +1,63 @@ +package fr.adrienbrault.idea.symfony2plugin.security; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.jetbrains.php.lang.psi.elements.StringLiteralExpression; +import de.espend.idea.php.annotation.extension.PhpAnnotationReferenceProvider; +import de.espend.idea.php.annotation.extension.parameter.AnnotationPropertyParameter; +import de.espend.idea.php.annotation.extension.parameter.PhpAnnotationReferenceProviderParameter; +import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent; +import fr.adrienbrault.idea.symfony2plugin.security.utils.VoterUtil; +import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Support: @IsGranted("VOTER_ATTRIBUTE") + */ +public class IsGrantedAnnotationReferences implements PhpAnnotationReferenceProvider { + private static String IS_GRANTED_CLASS = "Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\IsGranted"; + + @Nullable + @Override + public PsiReference[] getPropertyReferences(AnnotationPropertyParameter annotationPropertyParameter, PhpAnnotationReferenceProviderParameter phpAnnotationReferenceProviderParameter) { + Project project = annotationPropertyParameter.getProject(); + if(!Symfony2ProjectComponent.isEnabled(project) || !(annotationPropertyParameter.getElement() instanceof StringLiteralExpression) || !PhpElementsUtil.isEqualClassName(annotationPropertyParameter.getPhpClass(), IS_GRANTED_CLASS)) { + return new PsiReference[0]; + } + + if(annotationPropertyParameter.getType() != AnnotationPropertyParameter.Type.DEFAULT) { + return new PsiReference[0]; + } + + return new PsiReference[] { + new VoterReference(((StringLiteralExpression) annotationPropertyParameter.getElement())) + }; + } + + private static class VoterReference extends PsiPolyVariantReferenceBase { + @NotNull + private final StringLiteralExpression element; + + VoterReference(@NotNull StringLiteralExpression element) { + super(element); + this.element = element; + } + + @NotNull + @Override + public Object[] getVariants() { + VoterUtil.LookupElementPairConsumer consumer = new VoterUtil.LookupElementPairConsumer(); + VoterUtil.visitAttribute(this.myElement.getProject(), consumer); + return consumer.getLookupElements().toArray(); + } + + @NotNull + @Override + public ResolveResult[] multiResolve(boolean incompleteCode) { + VoterUtil.TargetPairConsumer voterConsumer = new VoterUtil.TargetPairConsumer(element.getContents()); + VoterUtil.visitAttribute(this.myElement.getProject(), voterConsumer); + return PsiElementResolveResult.createResults(voterConsumer.getValues()); + } + } +} diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index e72a3708e..85e908966 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -609,6 +609,9 @@ + + + diff --git a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/security/IsGrantedAnnotationReferencesTest.java b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/security/IsGrantedAnnotationReferencesTest.java new file mode 100644 index 000000000..607163982 --- /dev/null +++ b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/security/IsGrantedAnnotationReferencesTest.java @@ -0,0 +1,46 @@ +package fr.adrienbrault.idea.symfony2plugin.tests.security; + +import com.intellij.patterns.PlatformPatterns; +import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase; + +public class IsGrantedAnnotationReferencesTest extends SymfonyLightCodeInsightFixtureTestCase { + public void setUp() throws Exception { + super.setUp(); + + myFixture.copyFileToProject("security.yml"); + myFixture.copyFileToProject("classes.php"); + } + + protected String getTestDataPath() { + return "src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/security/fixtures"; + } + + public void testThatIsGrantedAnnotationProvidesCompletion() { + assertCompletionContains( + "test.php", + "\")\n" + + "*/\n" + + "function test() {};\n" + + "", + "YAML_ROLE_USER_FOOBAR" + ); + } + + public void testThatIsGrantedAnnotationProvidesRoleNavigation() { + assertReferenceMatchOnParent( + "test.php", + "_USER_FOOBAR\")\n" + + "*/\n" + + "function test() {};\n" + + "", + PlatformPatterns.psiElement() + ); + } +} diff --git a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/security/fixtures/classes.php b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/security/fixtures/classes.php index f150d10eb..e1279f849 100644 --- a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/security/fixtures/classes.php +++ b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/security/fixtures/classes.php @@ -8,12 +8,19 @@ public function isGranted($attributes, $object = null); } } -/** - * @Annotation - */ namespace Sensio\Bundle\FrameworkExtraBundle\Configuration { + /** + * @Annotation + */ class Security { } -} \ No newline at end of file + + /** + * @Annotation + */ + class IsGranted + { + } +}