Skip to content

Commit 9e62a68

Browse files
committed
Inject Expression Language into default annotation properties
1 parent 5f5022e commit 9e62a68

File tree

2 files changed

+88
-26
lines changed

2 files changed

+88
-26
lines changed

src/main/java/fr/adrienbrault/idea/symfony2plugin/lang/ParameterLanguageInjector.java

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
import com.intellij.lang.Language;
44
import com.intellij.lang.injection.MultiHostInjector;
55
import com.intellij.lang.injection.MultiHostRegistrar;
6+
import com.intellij.patterns.PlatformPatterns;
67
import com.intellij.psi.PsiElement;
78
import com.intellij.psi.PsiLanguageInjectionHost;
9+
import com.intellij.psi.PsiWhiteSpace;
10+
import com.jetbrains.php.lang.documentation.phpdoc.lexer.PhpDocTokenTypes;
11+
import com.jetbrains.php.lang.documentation.phpdoc.parser.PhpDocElementTypes;
812
import com.jetbrains.php.lang.documentation.phpdoc.psi.tags.PhpDocTag;
913
import com.jetbrains.php.lang.psi.elements.*;
1014
import com.jetbrains.php.lang.psi.elements.impl.ParameterListImpl;
@@ -53,7 +57,7 @@ public class ParameterLanguageInjector implements MultiHostInjector {
5357
new MethodCallArgumentLanguageInjection(LANGUAGE_ID_XPATH, XPATH_SIGNATURES),
5458
new MethodCallArgumentLanguageInjection(LANGUAGE_ID_JSON, JSON_SIGNATURES),
5559
new MethodCallArgumentLanguageInjection(LANGUAGE_ID_DQL, DQL_SIGNATURES),
56-
new MethodCallArgumentLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, EXPRESSION_LANGUAGE_SIGNATURES),
60+
new MethodCallArgumentLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, EXPRESSION_LANGUAGE_SIGNATURES),
5761
new NewExpressionLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Symfony\\Component\\ExpressionLanguage\\Expression", "expression", 0),
5862
new FunctionCallArgumentLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\expr", "expression", 0),
5963
new AttributeLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Symfony\\Component\\Validator\\Constraints\\Expression", "expression", 0),
@@ -64,12 +68,13 @@ public class ParameterLanguageInjector implements MultiHostInjector {
6468
new AttributeLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Entity", "expr", 1),
6569
new AttributeLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\ParamConverter", "expr", 1),
6670
new AttributeLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Route", "condition", 9),
67-
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Symfony\\Component\\Routing\\Annotation\\Route", "condition"),
68-
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Security", "expression"),
69-
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Cache", "lastModified"),
70-
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Cache", "Etag"),
71-
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Entity", "expr"),
72-
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\ParamConverter", "expr"),
71+
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Symfony\\Component\\Validator\\Constraints\\Expression", "expression", true),
72+
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Symfony\\Component\\Routing\\Annotation\\Route", "condition", false),
73+
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Security", "expression", true),
74+
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Cache", "lastModified", false),
75+
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Cache", "Etag", false),
76+
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Entity", "expr", false),
77+
new AnnotationLanguageInjection(LANGUAGE_ID_EXPRESSION_LANGUAGE, "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\ParamConverter", "expr", false),
7378
};
7479

7580
public static final String LANGUAGE_ID_CSS = "CSS";
@@ -406,15 +411,17 @@ public static class AnnotationLanguageInjection extends LanguageInjection {
406411
private final String classFQN;
407412
@NotNull
408413
private final String propertyName;
414+
private final boolean isDefaultProperty;
409415

410-
public AnnotationLanguageInjection(@NotNull String languageId, @NotNull String classFQN, @NotNull String propertyName) {
411-
this(languageId, null, null, classFQN, propertyName);
416+
public AnnotationLanguageInjection(@NotNull String languageId, @NotNull String classFQN, @NotNull String propertyName, boolean defaultProperty) {
417+
this(languageId, null, null, classFQN, propertyName, defaultProperty);
412418
}
413419

414-
public AnnotationLanguageInjection(@NotNull String languageId, @Nullable String prefix, @Nullable String suffix, @NotNull String classFQN, @NotNull String propertyName) {
420+
public AnnotationLanguageInjection(@NotNull String languageId, @Nullable String prefix, @Nullable String suffix, @NotNull String classFQN, @NotNull String propertyName, boolean defaultProperty) {
415421
super(languageId, prefix, suffix);
416422
this.classFQN = classFQN;
417423
this.propertyName = propertyName;
424+
this.isDefaultProperty = defaultProperty;
418425
}
419426

420427
@Override
@@ -427,11 +434,40 @@ public boolean accepts(@NotNull StringLiteralExpression element) {
427434

428435
var annotationClass = AnnotationUtil.getAnnotationReference(phpDocTag);
429436
if (annotationClass != null && annotationClass.getFQN().equals(classFQN)) {
430-
return element.equals(AnnotationUtil.getPropertyValueAsPsiElement(phpDocTag, propertyName));
437+
return element.equals(getPropertyValuePsiElement(phpDocTag));
431438
}
432439

433440
return false;
434441
}
442+
443+
@Nullable
444+
private PsiElement getPropertyValuePsiElement(@NotNull PhpDocTag phpDocTag) {
445+
PsiElement property = AnnotationUtil.getPropertyValueAsPsiElement(phpDocTag, propertyName);
446+
447+
if (property == null && isDefaultProperty) {
448+
var phpDocAttrList = phpDocTag.getFirstPsiChild();
449+
if (phpDocAttrList != null && phpDocAttrList.getNode().getElementType() == PhpDocElementTypes.phpDocAttributeList) {
450+
PhpPsiElement firstPhpPsiElement = phpDocAttrList.getFirstPsiChild();
451+
if (firstPhpPsiElement instanceof StringLiteralExpression && !hasIdentifier(firstPhpPsiElement)) {
452+
property = firstPhpPsiElement;
453+
}
454+
}
455+
}
456+
457+
return property;
458+
}
459+
460+
private boolean hasIdentifier(@NotNull PsiElement property) {
461+
return PlatformPatterns.psiElement()
462+
.afterLeafSkipping(
463+
PlatformPatterns.or(
464+
PlatformPatterns.psiElement(PsiWhiteSpace.class),
465+
PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_TEXT).withText("=")
466+
),
467+
PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_IDENTIFIER)
468+
)
469+
.accepts(property);
470+
}
435471
}
436472

437473
private static class NewExpressionLanguageInjection extends LanguageInjection {

src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/lang/ParameterLanguageInjectorTest.java

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,32 @@ public void testExpressionLanguageLanguageInjections() {
164164
LANGUAGE_ID_EXPRESSION_LANGUAGE
165165
);
166166

167+
assertInjectedLangAtCaret(
168+
PhpFileType.INSTANCE,
169+
"<?php\n" +
170+
"\n" +
171+
"use Symfony\\Component\\Validator\\Constraints\\Expression;\n" +
172+
"\n" +
173+
"/**\n" +
174+
" * @Expression(\"<caret>\")\n" +
175+
" */\n" +
176+
"class BlogPost {}\n",
177+
LANGUAGE_ID_EXPRESSION_LANGUAGE
178+
);
179+
180+
assertInjectedLangAtCaret(
181+
PhpFileType.INSTANCE,
182+
"<?php\n" +
183+
"\n" +
184+
"use Symfony\\Component\\Validator\\Constraints\\Expression;\n" +
185+
"\n" +
186+
"/**\n" +
187+
" * @Expression(expression: \"<caret>\")\n" +
188+
" */\n" +
189+
"class BlogPost {}\n",
190+
LANGUAGE_ID_EXPRESSION_LANGUAGE
191+
);
192+
167193
assertInjectedLangAtCaret(
168194
PhpFileType.INSTANCE,
169195
"<?php\n" +
@@ -203,21 +229,21 @@ public void testExpressionLanguageLanguageInjections() {
203229
LANGUAGE_ID_EXPRESSION_LANGUAGE
204230
);
205231

206-
// assertInjectedLangAtCaret(
207-
// PhpFileType.INSTANCE,
208-
// "<?php\n" +
209-
// "\n" +
210-
// "use Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Security;\n" +
211-
// "\n" +
212-
// "class ExampleController\n" +
213-
// "{\n" +
214-
// " /**\n" +
215-
// " * @Security(\"<caret>\")\n" +
216-
// " */\n" +
217-
// " public function contact() {}\n" +
218-
// "}",
219-
// LANGUAGE_ID_EXPRESSION_LANGUAGE
220-
// );
232+
assertInjectedLangAtCaret(
233+
PhpFileType.INSTANCE,
234+
"<?php\n" +
235+
"\n" +
236+
"use Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Security;\n" +
237+
"\n" +
238+
"class ExampleController\n" +
239+
"{\n" +
240+
" /**\n" +
241+
" * @Security(\"<caret>\")\n" +
242+
" */\n" +
243+
" public function contact() {}\n" +
244+
"}",
245+
LANGUAGE_ID_EXPRESSION_LANGUAGE
246+
);
221247

222248
assertInjectedLangAtCaret(
223249
PhpFileType.INSTANCE,

0 commit comments

Comments
 (0)