11package fr .adrienbrault .idea .symfony2plugin .security ;
22
33import com .intellij .codeInsight .completion .CompletionResultSet ;
4- import com .intellij .patterns . PatternCondition ;
4+ import com .intellij .openapi . util . text . StringUtil ;
55import com .intellij .patterns .PlatformPatterns ;
6+ import com .intellij .patterns .StandardPatterns ;
67import com .intellij .psi .PsiElement ;
7- import com .intellij .util .ProcessingContext ;
8- import com .jetbrains .php .lang .documentation .phpdoc .lexer .PhpDocTokenTypes ;
9- import com .jetbrains .php .lang .documentation .phpdoc .parser .PhpDocElementTypes ;
10- import com .jetbrains .php .lang .documentation .phpdoc .psi .tags .PhpDocTag ;
11- import com .jetbrains .php .lang .psi .elements .StringLiteralExpression ;
12- import de .espend .idea .php .annotation .util .AnnotationUtil ;
138import fr .adrienbrault .idea .symfony2plugin .codeInsight .GotoCompletionProvider ;
149import fr .adrienbrault .idea .symfony2plugin .codeInsight .GotoCompletionProviderLookupArguments ;
1510import fr .adrienbrault .idea .symfony2plugin .codeInsight .GotoCompletionRegistrar ;
1611import fr .adrienbrault .idea .symfony2plugin .codeInsight .GotoCompletionRegistrarParameter ;
12+ import fr .adrienbrault .idea .symfony2plugin .expressionLanguage .psi .*;
1713import fr .adrienbrault .idea .symfony2plugin .security .utils .VoterUtil ;
18- import fr .adrienbrault .idea .symfony2plugin .util .PhpElementsUtil ;
1914import org .jetbrains .annotations .NotNull ;
2015
2116import java .util .Collection ;
2217import java .util .Collections ;
2318import java .util .HashSet ;
24- import java .util .regex .Matcher ;
25- import java .util .regex .Pattern ;
2619
2720/**
2821 * @author Daniel Espendiller <daniel@espendiller.net>
2922 */
3023public class AnnotationExpressionGotoCompletionRegistrar implements GotoCompletionRegistrar {
3124
32- private static final String SECURITY_ANNOTATION = "Sensio\\ Bundle\\ FrameworkExtraBundle\\ Configuration\\ Security" ;
33-
3425 @ Override
3526 public void register (@ NotNull GotoCompletionRegistrarParameter registrar ) {
3627 // "@Security("is_granted('POST_SHOW', post) and has_role('ROLE_ADMIN')")"
3728 registrar .register (
38- PlatformPatterns .psiElement (PhpDocTokenTypes .DOC_STRING )
39- .withParent (PlatformPatterns .psiElement (StringLiteralExpression .class )
40- .withParent (PlatformPatterns .psiElement (PhpDocElementTypes .phpDocAttributeList )
41- .withParent (PlatformPatterns .psiElement (PhpDocTag .class )
42- .with (PhpDocInstancePatternCondition .INSTANCE )
29+ PlatformPatterns .psiElement ()
30+ .withParent (PlatformPatterns
31+ .psiElement (ExpressionLanguageStringLiteral .class )
32+ .withParent (PlatformPatterns
33+ .psiElement (ExpressionLanguageLiteralExpr .class )
34+ .withParent (PlatformPatterns
35+ .psiElement (ExpressionLanguageCallExpr .class )
36+ .withFirstChild (PlatformPatterns
37+ .psiElement (ExpressionLanguageRefExpr .class )
38+ .withText (StandardPatterns .string ().oneOf ("has_role" , "is_granted" ))
39+ )
40+ )
4341 )
44- )
45- ),
42+ ),
4643 MyGotoCompletionProvider ::new
4744 );
4845 }
@@ -59,75 +56,33 @@ private static class MyGotoCompletionProvider extends GotoCompletionProvider {
5956 @ Override
6057 public void getLookupElements (@ NotNull GotoCompletionProviderLookupArguments arguments ) {
6158 final CompletionResultSet resultSet = arguments .getResultSet ();
62- String blockNamePrefix = resultSet .getPrefixMatcher ().getPrefix ();
63-
64- // find caret position:
65- // - "has_role('"
66- // - "has_role('YAML_ROLE_"
67- if (!blockNamePrefix .matches ("^.*(has_role|is_granted)\\ s*\\ (\\ s*'[\\ w-]*$" )) {
68- return ;
69- }
70-
71- // clear prefix caret string; for a clean completion independent from inside content
72- CompletionResultSet myResultSet = resultSet .withPrefixMatcher ("" );
7359
7460 VoterUtil .LookupElementPairConsumer consumer = new VoterUtil .LookupElementPairConsumer ();
7561 VoterUtil .visitAttribute (getProject (), consumer );
76- myResultSet .addAllElements (consumer .getLookupElements ());
62+ resultSet .addAllElements (consumer .getLookupElements ());
7763 }
7864
7965 @ NotNull
8066 @ Override
8167 public Collection <PsiElement > getPsiTargets (PsiElement element ) {
82- if (getElement ().getNode ().getElementType () != PhpDocTokenTypes .DOC_STRING ) {
83- return Collections .emptyList ();
84- }
85-
86- PsiElement parent = getElement ().getParent ();
87- if (!(parent instanceof StringLiteralExpression )) {
68+ if (getElement ().getNode ().getElementType () != ExpressionLanguageTypes .STRING ) {
8869 return Collections .emptyList ();
8970 }
9071
91- String contents = ((StringLiteralExpression ) parent ).getContents ();
72+ var role = element .getText ();
73+ if (!StringUtil .isEmpty (role )) {
74+ var targets = new HashSet <PsiElement >();
9275
93- Collection <String > roles = new HashSet <>();
94- for (String regex : new String []{"is_granted\\ s*\\ (\\ s*['|\" ]([^'\" ]+)['|\" ]\\ s*[\\ )|,]" , "has_role\\ s*\\ (\\ s*['|\" ]([^'\" ]+)['|\" ]\\ s*\\ )" }) {
95- Matcher matcher = Pattern .compile (regex ).matcher (contents );
96- while (matcher .find ()){
97- roles .add (matcher .group (1 ));
98- }
99- }
76+ VoterUtil .visitAttribute (getProject (), pair -> {
77+ if (pair .getFirst ().equals (role .substring (1 , role .length () - 1 ))) {
78+ targets .add (pair .getSecond ());
79+ }
80+ });
10081
101- if (roles .size () == 0 ) {
102- return Collections .emptyList ();
82+ return targets ;
10383 }
10484
105- Collection <PsiElement > targets = new HashSet <>();
106-
107- VoterUtil .visitAttribute (getProject (), pair -> {
108- if (roles .contains (pair .getFirst ())) {
109- targets .add (pair .getSecond ());
110- }
111- });
112-
113- return targets ;
114- }
115- }
116-
117- /**
118- * Check if given PhpDocTag is instance of given Annotation class
119- */
120- private static class PhpDocInstancePatternCondition extends PatternCondition <PsiElement > {
121- private static PhpDocInstancePatternCondition INSTANCE = new PhpDocInstancePatternCondition ();
122-
123- PhpDocInstancePatternCondition () {
124- super ("PhpDoc Annotation Instance" );
125- }
126-
127- @ Override
128- public boolean accepts (@ NotNull PsiElement psiElement , ProcessingContext processingContext ) {
129- return psiElement instanceof PhpDocTag
130- && PhpElementsUtil .isEqualClassName (AnnotationUtil .getAnnotationReference ((PhpDocTag ) psiElement ), SECURITY_ANNOTATION );
85+ return Collections .emptyList ();
13186 }
13287 }
13388}
0 commit comments