Skip to content

Commit 36440af

Browse files
committed
[performance] speed up DoctrineMetadataFileStubIndex: replace recursive visitor with linear scan
1 parent db70972 commit 36440af

File tree

2 files changed

+45
-36
lines changed

2 files changed

+45
-36
lines changed

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

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,24 @@
88
import com.intellij.psi.xml.XmlAttribute;
99
import com.intellij.psi.xml.XmlFile;
1010
import com.intellij.psi.xml.XmlTag;
11+
import com.intellij.util.containers.ContainerUtil;
1112
import com.jetbrains.php.config.PhpLanguageLevel;
13+
import com.jetbrains.php.lang.documentation.phpdoc.PhpDocUtil;
1214
import com.jetbrains.php.lang.documentation.phpdoc.parser.PhpDocElementTypes;
1315
import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocComment;
1416
import com.jetbrains.php.lang.documentation.phpdoc.psi.tags.PhpDocTag;
1517
import com.jetbrains.php.lang.psi.PhpFile;
18+
import com.jetbrains.php.lang.psi.PhpPsiUtil;
19+
import com.jetbrains.php.lang.psi.elements.PhpAttribute;
1620
import com.jetbrains.php.lang.psi.elements.PhpClass;
21+
import com.jetbrains.php.lang.psi.elements.PhpNamedElement;
1722
import com.jetbrains.php.lang.psi.elements.PhpPsiElement;
1823
import com.jetbrains.php.refactoring.PhpNameUtil;
1924
import de.espend.idea.php.annotation.util.AnnotationUtil;
2025
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.visitor.AnnotationElementWalkingVisitor;
2126
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.visitor.AttributeElementWalkingVisitor;
27+
import fr.adrienbrault.idea.symfony2plugin.util.AnnotationBackportUtil;
28+
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
2229
import fr.adrienbrault.idea.symfony2plugin.util.PhpPsiAttributesUtil;
2330
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
2431
import fr.adrienbrault.idea.symfony2plugin.util.yaml.YamlHelper;
@@ -28,9 +35,7 @@
2835
import org.jetbrains.annotations.Nullable;
2936
import org.jetbrains.yaml.psi.*;
3037

31-
import java.util.ArrayList;
32-
import java.util.Collection;
33-
import java.util.Set;
38+
import java.util.*;
3439

3540
/**
3641
* @author Daniel Espendiller <daniel@espendiller.net>
@@ -57,8 +62,8 @@ public static Collection<Pair<String, String>> getClassRepositoryPair(@NotNull P
5762
pairs = getClassRepositoryPair((XmlFile) psiFile);
5863
} else if(psiFile instanceof YAMLFile) {
5964
pairs = getClassRepositoryPair((YAMLFile) psiFile);
60-
} else if(psiFile instanceof PhpFile) {
61-
pairs = getClassRepositoryPair((PsiElement) psiFile);
65+
} else if(psiFile instanceof PhpFile phpFile) {
66+
pairs = getClassRepositoryPair(phpFile);
6267
}
6368

6469
return pairs;
@@ -114,44 +119,48 @@ private static Collection<Pair<String, String>> getClassRepositoryPair(@NotNull
114119
* We support multiple use case like orm an so on
115120
*/
116121
@NotNull
117-
public static Collection<Pair<String, String>> getClassRepositoryPair(@NotNull PsiElement phpFile) {
122+
public static Collection<Pair<String, String>> getClassRepositoryPair(@NotNull PhpFile phpFile) {
118123
final Collection<Pair<String, String>> pairs = new ArrayList<>();
124+
Collection<PhpClass> classes = PhpPsiUtil.findAllClasses(phpFile);
119125

120-
// Annotations:
121-
// @ORM\Entity("repositoryClass": YYY)
122-
phpFile.acceptChildren(new AnnotationElementWalkingVisitor(phpDocTag -> {
123-
PhpDocComment phpDocComment = PsiTreeUtil.getParentOfType(phpDocTag, PhpDocComment.class);
124-
if (phpDocComment == null) {
125-
return false;
126+
for (PhpClass phpClass : classes) {
127+
PhpDocComment docComment = phpClass.getDocComment();
128+
if (docComment != null) {
129+
pairs.addAll(extractAnnotations(phpClass, docComment));
126130
}
127-
128-
PhpPsiElement phpClass = phpDocComment.getNextPsiSibling();
129-
if (!(phpClass instanceof PhpClass phpClassScope)) {
130-
return false;
131+
for (PhpAttribute attribute : phpClass.getAttributes()) {
132+
String attributeFQN = attribute.getFQN();
133+
if (attributeFQN == null) continue;
134+
if (PhpElementsUtil.isEqualClassName(attributeFQN, MODEL_CLASS_ANNOTATION)) {
135+
String repositoryClass = PhpPsiAttributesUtil.getAttributeValueByNameAsString(attribute, "repositoryClass");
136+
pairs.add(Pair.create(StringUtils.stripStart(phpClass.getFQN(), "\\"),
137+
repositoryClass != null ? StringUtils.stripStart(repositoryClass, "\\") : null));
138+
}
131139
}
140+
}
132141

133-
pairs.add(Pair.create(
134-
phpClassScope.getPresentableFQN(),
135-
getAnnotationRepositoryClass(phpDocTag, phpClassScope))
136-
);
137-
138-
return false;
139-
}, MODEL_CLASS_ANNOTATION));
140-
141-
// Attributes:
142-
// #[Entity(repositoryClass: UserRepository::class)]
143-
phpFile.acceptChildren(new AttributeElementWalkingVisitor(pair -> {
144-
String repositoryClass = PhpPsiAttributesUtil.getAttributeValueByNameAsString(pair.getFirst(), "repositoryClass");
142+
return pairs;
143+
}
145144

146-
pairs.add(Pair.create(
147-
StringUtils.stripStart(pair.getSecond().getFQN(), "\\"),
148-
repositoryClass != null ? StringUtils.stripStart(repositoryClass, "\\") : null
149-
));
145+
public static Collection<Pair<String, String>> extractAnnotations(@NotNull PhpClass phpClass, @NotNull PhpDocComment docComment) {
146+
Collection<Pair<String, String>> result = new ArrayList<>();
147+
PhpDocUtil.processTagElementsByName(docComment, null, phpDocTag -> {
148+
if (AnnotationBackportUtil.NON_ANNOTATION_TAGS.contains(phpDocTag.getName())) {
149+
return true;
150+
}
150151

151-
return false;
152-
}, MODEL_CLASS_ANNOTATION));
152+
Map<String, String> fileImports = AnnotationBackportUtil.getUseImportMap(phpDocTag);
153+
if (fileImports.isEmpty()) {
154+
return true;
155+
}
153156

154-
return pairs;
157+
String annotationFqnName = AnnotationBackportUtil.getClassNameReference(phpDocTag, fileImports);
158+
if (ContainerUtil.exists(MODEL_CLASS_ANNOTATION, c -> c.equals(annotationFqnName))) {
159+
result.add(Pair.create(phpClass.getPresentableFQN(), getAnnotationRepositoryClass(phpDocTag, phpClass)));
160+
}
161+
return true;
162+
});
163+
return result;
155164
}
156165

157166
/**

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public static PhpClass getEntityRepositoryClass(@NotNull Project project, @NotNu
9292
if(docAnnotation != null) {
9393
// search for repositoryClass="Foo\Bar\RegisterRepository"; repositoryClass=Foo\Bar\RegisterRepository::class
9494
// @MongoDB\Document; @ORM\Entity
95-
Collection<Pair<String, String>> classRepositoryPair = DoctrineUtil.getClassRepositoryPair(docAnnotation);
95+
Collection<Pair<String, String>> classRepositoryPair = DoctrineUtil.extractAnnotations(phpClass, docAnnotation);
9696
if (!classRepositoryPair.isEmpty()) {
9797
Pair<String, String> next = classRepositoryPair.iterator().next();
9898
if (next.getSecond() != null) {

0 commit comments

Comments
 (0)