Skip to content

Commit 2c7e7d6

Browse files
authored
Merge pull request #2076 from Haehnchen/feature/repo-attribute
fix attribute resolve for class constants to support repositoryClass …
2 parents 6f317c2 + 59440dc commit 2c7e7d6

File tree

5 files changed

+117
-26
lines changed

5 files changed

+117
-26
lines changed

src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/DoctrineUtil.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@
1414
import com.jetbrains.php.lang.psi.PhpFile;
1515
import com.jetbrains.php.lang.psi.elements.PhpClass;
1616
import com.jetbrains.php.lang.psi.elements.PhpPsiElement;
17-
import com.jetbrains.php.lang.psi.stubs.indexes.expectedArguments.PhpExpectedFunctionArgument;
18-
import com.jetbrains.php.lang.psi.stubs.indexes.expectedArguments.PhpExpectedFunctionClassConstantArgument;
1917
import de.espend.idea.php.annotation.util.AnnotationUtil;
2018
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.visitor.AnnotationElementWalkingVisitor;
2119
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.visitor.AttributeElementWalkingVisitor;
22-
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
20+
import fr.adrienbrault.idea.symfony2plugin.util.PhpPsiAttributesUtil;
2321
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
2422
import fr.adrienbrault.idea.symfony2plugin.util.yaml.YamlHelper;
2523
import org.apache.commons.lang.ArrayUtils;
@@ -141,15 +139,7 @@ public static Collection<Pair<String, String>> getClassRepositoryPair(@NotNull P
141139
// Attributes:
142140
// #[Entity(repositoryClass: UserRepository::class)]
143141
phpFile.acceptChildren(new AttributeElementWalkingVisitor(pair -> {
144-
String repositoryClass = null;
145-
146-
PhpExpectedFunctionArgument argument = PhpElementsUtil.findAttributeArgumentByName("repositoryClass", pair.getFirst());
147-
if (argument instanceof PhpExpectedFunctionClassConstantArgument) {
148-
String repositoryClassRaw = ((PhpExpectedFunctionClassConstantArgument) argument).getClassFqn();
149-
if (StringUtils.isNotBlank(repositoryClassRaw)) {
150-
repositoryClass = repositoryClassRaw;
151-
}
152-
}
142+
String repositoryClass = PhpPsiAttributesUtil.getAttributeValueByNameAsString(pair.getFirst(), "repositoryClass");
153143

154144
pairs.add(Pair.create(
155145
StringUtils.stripStart(pair.getSecond().getFQN(), "\\"),

src/main/java/fr/adrienbrault/idea/symfony2plugin/util/PhpPsiAttributesUtil.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -180,29 +180,36 @@ private static PsiElementPattern.Capture<PsiElement> getAttributeColonPattern(St
180180
@Nullable
181181
private static String resolveLocalValue(@NotNull PhpAttribute attribute, @NotNull ClassConstantReference nextSibling) {
182182
PhpExpression classReference = nextSibling.getClassReference();
183-
if (classReference != null) {
183+
if (classReference instanceof ClassReference) {
184184
String name = classReference.getName();
185185
if (name != null && (name.equals("self") || name.equals("static"))) {
186186
PsiElement phpAttributesList = attribute.getParent();
187187
if (phpAttributesList instanceof PhpAttributesList) {
188188
PsiElement method = phpAttributesList.getParent();
189-
if (method instanceof Method) {
190-
PsiElement phpClass = method.getParent();
191-
if (phpClass instanceof PhpClass) {
192-
String fieldName = nextSibling.getName();
193-
Field ownFieldByName = ((PhpClass) phpClass).findOwnFieldByName(fieldName, true);
194-
if (ownFieldByName != null) {
195-
PsiElement defaultValue = ownFieldByName.getDefaultValue();
196-
if (defaultValue instanceof StringLiteralExpression) {
197-
String contents = ((StringLiteralExpression) defaultValue).getContents();
198-
if (StringUtils.isNotBlank(contents)) {
199-
return contents;
200-
}
189+
190+
PsiElement phpClass = method instanceof Method ? ((Method) method).getContainingClass() : method;
191+
if (phpClass instanceof PhpClass) {
192+
String fieldName = nextSibling.getName();
193+
Field ownFieldByName = ((PhpClass) phpClass).findOwnFieldByName(fieldName, true);
194+
if (ownFieldByName != null) {
195+
PsiElement defaultValue = ownFieldByName.getDefaultValue();
196+
if (defaultValue instanceof StringLiteralExpression) {
197+
String contents = ((StringLiteralExpression) defaultValue).getContents();
198+
if (StringUtils.isNotBlank(contents)) {
199+
return contents;
201200
}
202201
}
203202
}
204203
}
205204
}
205+
} else {
206+
String s = nextSibling.getText().toLowerCase();
207+
if (s.endsWith("::class")) {
208+
String fqn = ((ClassReference) classReference).getFQN();
209+
if (StringUtils.isNotBlank(fqn)) {
210+
return fqn;
211+
}
212+
}
206213
}
207214
}
208215

src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/stubs/indexes/DoctrineMetadataFileStubIndexTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ public void testPhpOrmAnnotationMetadata() {
148148
assertIndexContainsKeyWithValue(DoctrineMetadataFileStubIndex.KEY, "Doctrine\\Orm\\Annotation", new IndexValueRepositoryClassEquals("Doctrine\\Orm\\Foo"));
149149
}
150150

151+
public void testPhpOrmAttributeMetadata() {
152+
assertIndexContains(DoctrineMetadataFileStubIndex.KEY, "Doctrine\\Orm\\AttributeEntity");
153+
assertIndexContainsKeyWithValue(DoctrineMetadataFileStubIndex.KEY, "Doctrine\\Orm\\AttributeEntity", new IndexValueRepositoryClassEquals("Doctrine\\OrmRepository\\AttributeEntityRepository"));
154+
}
155+
151156
/**
152157
* @see fr.adrienbrault.idea.symfony2plugin.doctrine.DoctrineUtil#getClassRepositoryPair
153158
*/

src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/stubs/indexes/fixtures/doctrine.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,19 @@ class Document {};
1919
namespace Doctrine\Orm {
2020

2121
use Doctrine\ORM\Mapping AS ORM;
22+
use Doctrine\OrmRepository\AttributeEntityRepository;
2223

2324
/**
2425
* @ORM\Entity(repositoryClass="Foo")
2526
*/
26-
class Annotation {};
27+
class Annotation {}
28+
29+
#[ORM\Entity(repositoryClass: AttributeEntityRepository::class)]
30+
class AttributeEntity {}
31+
}
2732

33+
namespace Doctrine\OrmRepository {
34+
class AttributeEntityRepository {};
2835
}
2936

3037
namespace Doctrine\Flow\Orm {
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package fr.adrienbrault.idea.symfony2plugin.tests.util;
2+
3+
import com.jetbrains.php.lang.psi.PhpPsiElementFactory;
4+
import com.jetbrains.php.lang.psi.elements.PhpAttribute;
5+
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
6+
import fr.adrienbrault.idea.symfony2plugin.util.PhpPsiAttributesUtil;
7+
8+
/**
9+
* @author Daniel Espendiller <daniel@espendiller.net>
10+
*/
11+
public class PhpPsiAttributesUtilTest extends SymfonyLightCodeInsightFixtureTestCase {
12+
public void testGetAttributeValueByNameAsStringForDirectResolve() {
13+
PhpAttribute phpAttribute1 = PhpPsiElementFactory.createFromText(getProject(), PhpAttribute.class, "<?php\n" +
14+
"#[Foobar(test: 'foobar')]" +
15+
"class Foo {}"
16+
);
17+
18+
assertEquals("foobar", PhpPsiAttributesUtil.getAttributeValueByNameAsString(phpAttribute1, "test"));
19+
20+
PhpAttribute phpAttribute2 = PhpPsiElementFactory.createFromText(getProject(), PhpAttribute.class, "<?php\n" +
21+
"class Foobar {}" +
22+
"\n" +
23+
"#[Foobar(test: Foobar::class)]\n" +
24+
"class Foo {}"
25+
);
26+
27+
assertEquals("\\Foobar", PhpPsiAttributesUtil.getAttributeValueByNameAsString(phpAttribute2, "test"));
28+
}
29+
30+
public void testGetAttributeValueByNameAsStringForLocalResolve() {
31+
PhpAttribute phpAttribute1 = PhpPsiElementFactory.createFromText(getProject(), PhpAttribute.class, "<?php\n" +
32+
"\n" +
33+
"#[Foobar(test: self::FOO)]\n" +
34+
"class Foo {\n" +
35+
" const FOO = 'test2';" +
36+
"}"
37+
);
38+
39+
assertEquals("test2", PhpPsiAttributesUtil.getAttributeValueByNameAsString(phpAttribute1, "test"));
40+
41+
PhpAttribute phpAttribute2 = PhpPsiElementFactory.createFromText(getProject(), PhpAttribute.class, "<?php\n" +
42+
"\n" +
43+
"class Foo {\n" +
44+
" const FOO = 'test2';\n" +
45+
"\n" +
46+
"#[Foobar(test: self::FOO)]\n" +
47+
" public function foo() {}\n" +
48+
"}"
49+
);
50+
51+
assertEquals("test2", PhpPsiAttributesUtil.getAttributeValueByNameAsString(phpAttribute2, "test"));
52+
53+
PhpAttribute phpAttribute3 = PhpPsiElementFactory.createFromText(getProject(), PhpAttribute.class, "<?php\n" +
54+
"\n" +
55+
"class Foo {\n" +
56+
" const FOO = 'test2';\n" +
57+
"\n" +
58+
"#[Foobar(test: static::FOO)]\n" +
59+
" public function foo() {}\n" +
60+
"}"
61+
);
62+
63+
assertEquals("test2", PhpPsiAttributesUtil.getAttributeValueByNameAsString(phpAttribute3, "test"));
64+
}
65+
66+
public void testResolveForNoLocalValue() {
67+
PhpAttribute phpAttribute = PhpPsiElementFactory.createFromText(getProject(), PhpAttribute.class, "<?php\n" +
68+
"class FooBar {\n" +
69+
" const BAR = 'test2';\n" +
70+
"}\n" +
71+
"\n" +
72+
"class Foo {\n" +
73+
" const FOO = 'test2';\n" +
74+
"\n" +
75+
"#[Foobar(test: FooBar::BAR)]\n" +
76+
" public function foo() {}\n" +
77+
"}"
78+
);
79+
80+
assertNull(PhpPsiAttributesUtil.getAttributeValueByNameAsString(phpAttribute, "test"));
81+
}
82+
}

0 commit comments

Comments
 (0)