1
1
package fr .adrienbrault .idea .symfony2plugin .security ;
2
2
3
3
import com .intellij .codeInsight .completion .CompletionResultSet ;
4
- import com .intellij .patterns . PatternCondition ;
4
+ import com .intellij .openapi . util . text . StringUtil ;
5
5
import com .intellij .patterns .PlatformPatterns ;
6
+ import com .intellij .patterns .StandardPatterns ;
6
7
import 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 ;
13
8
import fr .adrienbrault .idea .symfony2plugin .codeInsight .GotoCompletionProvider ;
14
9
import fr .adrienbrault .idea .symfony2plugin .codeInsight .GotoCompletionProviderLookupArguments ;
15
10
import fr .adrienbrault .idea .symfony2plugin .codeInsight .GotoCompletionRegistrar ;
16
11
import fr .adrienbrault .idea .symfony2plugin .codeInsight .GotoCompletionRegistrarParameter ;
12
+ import fr .adrienbrault .idea .symfony2plugin .expressionLanguage .psi .*;
17
13
import fr .adrienbrault .idea .symfony2plugin .security .utils .VoterUtil ;
18
- import fr .adrienbrault .idea .symfony2plugin .util .PhpElementsUtil ;
19
14
import org .jetbrains .annotations .NotNull ;
20
15
21
16
import java .util .Collection ;
22
17
import java .util .Collections ;
23
18
import java .util .HashSet ;
24
- import java .util .regex .Matcher ;
25
- import java .util .regex .Pattern ;
26
19
27
20
/**
28
21
* @author Daniel Espendiller <daniel@espendiller.net>
29
22
*/
30
23
public class AnnotationExpressionGotoCompletionRegistrar implements GotoCompletionRegistrar {
31
24
32
- private static final String SECURITY_ANNOTATION = "Sensio\\ Bundle\\ FrameworkExtraBundle\\ Configuration\\ Security" ;
33
-
34
25
@ Override
35
26
public void register (@ NotNull GotoCompletionRegistrarParameter registrar ) {
36
27
// "@Security("is_granted('POST_SHOW', post) and has_role('ROLE_ADMIN')")"
37
28
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
+ )
43
41
)
44
- )
45
- ),
42
+ ),
46
43
MyGotoCompletionProvider ::new
47
44
);
48
45
}
@@ -59,75 +56,33 @@ private static class MyGotoCompletionProvider extends GotoCompletionProvider {
59
56
@ Override
60
57
public void getLookupElements (@ NotNull GotoCompletionProviderLookupArguments arguments ) {
61
58
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 ("" );
73
59
74
60
VoterUtil .LookupElementPairConsumer consumer = new VoterUtil .LookupElementPairConsumer ();
75
61
VoterUtil .visitAttribute (getProject (), consumer );
76
- myResultSet .addAllElements (consumer .getLookupElements ());
62
+ resultSet .addAllElements (consumer .getLookupElements ());
77
63
}
78
64
79
65
@ NotNull
80
66
@ Override
81
67
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 ) {
88
69
return Collections .emptyList ();
89
70
}
90
71
91
- String contents = ((StringLiteralExpression ) parent ).getContents ();
72
+ var role = element .getText ();
73
+ if (!StringUtil .isEmpty (role )) {
74
+ var targets = new HashSet <PsiElement >();
92
75
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
+ });
100
81
101
- if (roles .size () == 0 ) {
102
- return Collections .emptyList ();
82
+ return targets ;
103
83
}
104
84
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 ();
131
86
}
132
87
}
133
88
}
0 commit comments