Skip to content

Commit 4e5e8e4

Browse files
committed
optimize performance for inspection iteration
1 parent ab5e1f5 commit 4e5e8e4

14 files changed

Lines changed: 87 additions & 38 deletions

src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/inspection/ServiceNamedArgumentExistsInspection.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder, bool
3131

3232
private static class MyPsiElementVisitor extends PsiElementVisitor {
3333
@NotNull private final ProblemsHolder holder;
34+
private ContainerCollectionResolver.LazyServiceCollector lazyServiceCollector;
3435
private ElementPattern<?> namedArgumentPattern;
3536

3637
MyPsiElementVisitor(@NotNull ProblemsHolder holder) {
@@ -40,14 +41,18 @@ private static class MyPsiElementVisitor extends PsiElementVisitor {
4041
@Override
4142
public void visitElement(@NotNull PsiElement element) {
4243
if (getNamedArgumentPattern().accepts(element)) {
43-
if (isSupportedDefinition(element) && ServiceContainerUtil.hasMissingYamlNamedArgumentForInspection(element, new ContainerCollectionResolver.LazyServiceCollector(holder.getProject()))) {
44+
if (isSupportedDefinition(element) && ServiceContainerUtil.hasMissingYamlNamedArgumentForInspection(element, getLazyServiceCollector())) {
4445
holder.registerProblem(element, INSPECTION_MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
4546
}
4647
}
4748

4849
super.visitElement(element);
4950
}
5051

52+
private ContainerCollectionResolver.LazyServiceCollector getLazyServiceCollector() {
53+
return lazyServiceCollector != null ? lazyServiceCollector : (lazyServiceCollector = new ContainerCollectionResolver.LazyServiceCollector(holder.getProject()));
54+
}
55+
5156
private ElementPattern<?> getNamedArgumentPattern() {
5257
return namedArgumentPattern != null ? namedArgumentPattern : (namedArgumentPattern = YamlElementPatternHelper.getNamedArgumentPattern());
5358
}

src/main/java/fr/adrienbrault/idea/symfony2plugin/intentions/php/AddRouteAttributeIntention.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,15 @@ public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull Psi
109109
return false;
110110
}
111111

112-
if (!PhpElementsUtil.hasClassOrInterface(project, ROUTE_ATTRIBUTE_CLASS)) {
112+
if (hasRouteAttribute(method)) {
113113
return false;
114114
}
115115

116-
if (hasRouteAttribute(method)) {
116+
if (!isControllerClass(phpClass)) {
117117
return false;
118118
}
119119

120-
return isControllerClass(phpClass);
120+
return PhpElementsUtil.hasClassOrInterface(project, ROUTE_ATTRIBUTE_CLASS);
121121
}
122122

123123
private boolean hasRouteAttribute(@NotNull Method method) {

src/main/java/fr/adrienbrault/idea/symfony2plugin/intentions/php/CommandInvokeParameterIntention.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,11 @@ public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull Psi
137137
return false;
138138
}
139139

140-
if (PhpElementsUtil.isInstanceOf(phpClass, "\\Symfony\\Component\\Console\\Command\\Command")) {
140+
if (phpClass.getAttributes(AS_COMMAND_ATTRIBUTE).isEmpty()) {
141141
return false;
142142
}
143143

144-
if (phpClass.getAttributes(AS_COMMAND_ATTRIBUTE).isEmpty()) {
144+
if (PhpElementsUtil.isInstanceOf(phpClass, "\\Symfony\\Component\\Console\\Command\\Command")) {
145145
return false;
146146
}
147147

src/main/java/fr/adrienbrault/idea/symfony2plugin/routing/inspection/PhpRouteMissingInspection.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.intellij.codeInspection.ProblemsHolder;
77
import com.intellij.psi.PsiElement;
88
import com.intellij.psi.PsiElementVisitor;
9+
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
910
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
1011
import fr.adrienbrault.idea.symfony2plugin.routing.PhpRouteReferenceContributor;
1112
import fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper;
@@ -38,7 +39,7 @@ private static class MyPsiElementVisitor extends PsiElementVisitor {
3839

3940
@Override
4041
public void visitElement(@NotNull PsiElement element) {
41-
if(getMethodWithFirstStringPattern().accepts(element)) {
42+
if(element instanceof StringLiteralExpression && getMethodWithFirstStringPattern().accepts(element)) {
4243
String contents = PhpElementsUtil.getStringValue(element);
4344
if(StringUtils.isNotBlank(contents)) {
4445
invoke(contents, element, holder);

src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/PhpTemplateMissingInspection.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,16 @@ public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean is
3535
return new PsiElementVisitor() {
3636
@Override
3737
public void visitElement(@NotNull PsiElement element) {
38-
invoke(holder, element);
38+
if (element instanceof StringLiteralExpression stringLiteralExpression) {
39+
invoke(holder, stringLiteralExpression);
40+
}
3941
super.visitElement(element);
4042
}
4143
};
4244
}
4345

44-
private void invoke(@NotNull ProblemsHolder holder, @NotNull PsiElement psiElement) {
45-
if (!(psiElement instanceof StringLiteralExpression)) {
46-
return;
47-
}
48-
49-
String templateNameIfMissing = getTemplateNameIfMissing((StringLiteralExpression) psiElement);
46+
private void invoke(@NotNull ProblemsHolder holder, @NotNull StringLiteralExpression psiElement) {
47+
String templateNameIfMissing = getTemplateNameIfMissing(psiElement);
5048
if(templateNameIfMissing == null) {
5149
return;
5250
}

src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/TwigHtmlLineMarkerProvider.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,25 @@
2525

2626
import java.util.ArrayList;
2727
import java.util.Collection;
28+
import java.util.HashMap;
2829
import java.util.List;
2930
import java.util.Map;
3031
import java.util.function.Supplier;
3132

3233
public class TwigHtmlLineMarkerProvider implements LineMarkerProvider {
3334
@Override
3435
public void collectSlowLineMarkers(@NotNull List<? extends PsiElement> psiElements, @NotNull Collection<? super LineMarkerInfo<?>> results) {
35-
if (psiElements.isEmpty() || !Symfony2ProjectComponent.isEnabled(psiElements.get(0))) {
36+
if (psiElements.isEmpty() || !Symfony2ProjectComponent.isEnabled(psiElements.getFirst())) {
3637
return;
3738
}
3839

39-
PsiFile file = psiElements.get(0).getContainingFile();
40+
PsiFile file = psiElements.getFirst().getContainingFile();
4041
if (!isSupportedFile(file)) {
4142
return;
4243
}
4344

45+
Map<String, Boolean> componentBlockExistsCache = new HashMap<>();
46+
4447
for (PsiElement psiElement : psiElements) {
4548
if (!(psiElement instanceof XmlToken xmlToken) || xmlToken.getNode().getElementType() != XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) {
4649
continue;
@@ -50,7 +53,7 @@ public void collectSlowLineMarkers(@NotNull List<? extends PsiElement> psiElemen
5053
continue;
5154
}
5255

53-
LineMarkerInfo<?> blockOverride = attachTwigComponentBlockOverride(xmlAttributeValue, xmlToken);
56+
LineMarkerInfo<?> blockOverride = attachTwigComponentBlockOverride(xmlAttributeValue, xmlToken, componentBlockExistsCache);
5457
if (blockOverride != null) {
5558
results.add(blockOverride);
5659
}
@@ -68,7 +71,7 @@ public static boolean isSupportedFile(@Nullable PsiFile file) {
6871
}
6972

7073
@Nullable
71-
protected LineMarkerInfo<?> attachTwigComponentBlockOverride(@NotNull XmlAttributeValue xmlAttributeValue, @NotNull PsiElement lineMarkerTarget) {
74+
protected LineMarkerInfo<?> attachTwigComponentBlockOverride(@NotNull XmlAttributeValue xmlAttributeValue, @NotNull PsiElement lineMarkerTarget, @NotNull Map<String, Boolean> componentBlockExistsCache) {
7275
if (!(xmlAttributeValue.getParent() instanceof XmlAttribute xmlAttribute) || !"name".equals(xmlAttribute.getName())) {
7376
return null;
7477
}
@@ -100,7 +103,8 @@ protected LineMarkerInfo<?> attachTwigComponentBlockOverride(@NotNull XmlAttribu
100103
}
101104

102105
Project project = xmlAttributeValue.getProject();
103-
if (!hasComponentBlock(project, componentName, blockName)) {
106+
String cacheKey = componentName + "\0" + blockName;
107+
if (!componentBlockExistsCache.computeIfAbsent(cacheKey, ignored -> hasComponentBlock(project, componentName, blockName))) {
104108
return null;
105109
}
106110

@@ -111,6 +115,11 @@ protected LineMarkerInfo<?> attachTwigComponentBlockOverride(@NotNull XmlAttribu
111115
return builder.createLineMarkerInfo(lineMarkerTarget);
112116
}
113117

118+
@Nullable
119+
protected LineMarkerInfo<?> attachTwigComponentBlockOverride(@NotNull XmlAttributeValue xmlAttributeValue, @NotNull PsiElement lineMarkerTarget) {
120+
return attachTwigComponentBlockOverride(xmlAttributeValue, lineMarkerTarget, new HashMap<>());
121+
}
122+
114123
@Nullable
115124
protected String resolveComponentName(@NotNull Project project, @NotNull String rawComponentName) {
116125
return UxUtil.resolveTwigComponentName(project, rawComponentName);

src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/inspection/PhpAssetMissingInspection.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ private static class AssetPackageElementVisitor extends PsiElementVisitor {
4242
public void visitElement(@NotNull PsiElement element) {
4343
if (element instanceof StringLiteralExpression) {
4444
MethodReference methodReference = PsiElementUtils.getMethodReferenceWithFirstStringParameter((StringLiteralExpression) element);
45-
if (methodReference != null && (PhpElementsUtil.isMethodReferenceInstanceOf(methodReference, "\\Symfony\\Component\\Asset\\Packages", "getUrl")
45+
String methodName = methodReference != null ? methodReference.getName() : null;
46+
if (methodName != null && ("getUrl".equals(methodName) || "getVersion".equals(methodName)) && (PhpElementsUtil.isMethodReferenceInstanceOf(methodReference, "\\Symfony\\Component\\Asset\\Packages", "getUrl")
4647
|| PhpElementsUtil.isMethodReferenceInstanceOf(methodReference, "\\Symfony\\Component\\Asset\\Packages", "getVersion")
4748
|| PhpElementsUtil.isMethodReferenceInstanceOf(methodReference, "\\Symfony\\Component\\Asset\\PackageInterface", "getUrl")
4849
|| PhpElementsUtil.isMethodReferenceInstanceOf(methodReference, "\\Symfony\\Component\\Asset\\PackageInterface", "getVersion")

src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/inspection/TemplateMissingAnnotationPhpAttributeLocalInspection.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
public class TemplateMissingAnnotationPhpAttributeLocalInspection extends LocalInspectionTool {
3030
@NotNull
3131
public PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder, boolean isOnTheFly) {
32+
if (!Symfony2ProjectComponent.isEnabled(holder.getProject())) {
33+
return super.buildVisitor(holder, isOnTheFly);
34+
}
35+
3236
return new PsiElementVisitor() {
3337
@Override
3438
public void visitElement(@NotNull PsiElement element) {
@@ -38,7 +42,7 @@ public void visitElement(@NotNull PsiElement element) {
3842

3943
if (element instanceof PhpAttribute) {
4044
String fqn = ((PhpAttribute) element).getFQN();
41-
if (fqn != null && Arrays.stream(TwigUtil.TEMPLATE_ANNOTATION_CLASS).anyMatch(s -> PhpElementsUtil.isInstanceOf(element.getProject(), fqn, s))) {
45+
if (fqn != null && PhpElementsUtil.isEqualClassName(fqn, TwigUtil.TEMPLATE_ANNOTATION_CLASS)) {
4246
annotate((PhpAttribute) element, holder);
4347
}
4448
}
@@ -74,10 +78,6 @@ private void annotate(@NotNull PhpAttribute phpAttribute, @NotNull ProblemsHolde
7478
}
7579

7680
private void annotate(@NotNull PhpDocTag phpDocTag, @NotNull ProblemsHolder holder) {
77-
if(!Symfony2ProjectComponent.isEnabled(phpDocTag.getProject())) {
78-
return;
79-
}
80-
8181
PhpDocTagAnnotation phpDocAnnotationContainer = AnnotationUtil.getPhpDocAnnotationContainer(phpDocTag);
8282
if (phpDocAnnotationContainer == null || !PhpElementsUtil.isEqualClassName(phpDocAnnotationContainer.getPhpClass(), TwigUtil.TEMPLATE_ANNOTATION_CLASS)) {
8383
return;

src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/inspection/TwigAssetMissingInspection.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
import com.intellij.codeInspection.ProblemsHolder;
66
import com.intellij.psi.PsiElement;
77
import com.intellij.psi.PsiElementVisitor;
8+
import com.intellij.psi.impl.source.tree.LeafPsiElement;
9+
import com.jetbrains.twig.TwigTokenTypes;
810
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
911
import fr.adrienbrault.idea.symfony2plugin.templating.TwigPattern;
1012
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigUtil;
1113
import org.apache.commons.lang3.StringUtils;
1214
import org.jetbrains.annotations.NotNull;
15+
import org.jspecify.annotations.NonNull;
1316

1417
/**
1518
* asset('<caret>')
@@ -36,7 +39,12 @@ private static class MyPsiElementVisitor extends PsiElementVisitor {
3639
}
3740

3841
@Override
39-
public void visitElement(PsiElement element) {
42+
public void visitElement(@NonNull PsiElement element) {
43+
if (!(element instanceof LeafPsiElement) || element.getNode().getElementType() != TwigTokenTypes.STRING_TEXT) {
44+
super.visitElement(element);
45+
return;
46+
}
47+
4048
if(getAssetPattern().accepts(element) && TwigUtil.isValidStringWithoutInterpolatedOrConcat(element)) {
4149
invoke(element, holder);
4250
}

src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/inspection/TwigEnumFunctionInspection.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.intellij.codeInspection.ProblemHighlightType;
55
import com.intellij.patterns.ElementPattern;
66
import com.intellij.codeInspection.ProblemsHolder;
7+
import com.intellij.lang.ASTNode;
78
import com.intellij.psi.PsiElement;
89
import com.intellij.psi.PsiElementVisitor;
910
import com.intellij.psi.impl.source.tree.LeafPsiElement;
@@ -51,7 +52,13 @@ private static class MyPsiElementVisitor extends PsiElementVisitor {
5152
@Override
5253
public void visitElement(@NotNull PsiElement element) {
5354
// Fast pre-filter: only STRING_TEXT elements can be enum/enum_cases arguments
54-
if (element instanceof LeafPsiElement && element.getNode() == null || element.getNode().getElementType() != TwigTokenTypes.STRING_TEXT) {
55+
if (!(element instanceof LeafPsiElement)) {
56+
super.visitElement(element);
57+
return;
58+
}
59+
60+
ASTNode node = element.getNode();
61+
if (node == null || node.getElementType() != TwigTokenTypes.STRING_TEXT) {
5562
super.visitElement(element);
5663
return;
5764
}

0 commit comments

Comments
 (0)