Skip to content

Commit 221ad5c

Browse files
AlexMovsesovAleksander Movsesov
authored and
Aleksander Movsesov
committed
Container stub index performance: move to unrecursive indexer
1 parent f58cc67 commit 221ad5c

File tree

1 file changed

+47
-78
lines changed

1 file changed

+47
-78
lines changed

src/main/java/fr/adrienbrault/idea/symfony2plugin/stubs/indexes/ContainerBuilderStubIndex.java

+47-78
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
11
package fr.adrienbrault.idea.symfony2plugin.stubs.indexes;
22

33
import com.intellij.openapi.vfs.VfsUtil;
4-
import com.intellij.psi.PsiElement;
54
import com.intellij.psi.PsiFile;
6-
import com.intellij.psi.PsiRecursiveElementVisitor;
7-
import com.intellij.psi.util.PsiTreeUtil;
85
import com.intellij.util.ObjectUtils;
96
import com.intellij.util.containers.HashSet;
107
import com.intellij.util.indexing.*;
118
import com.intellij.util.io.DataExternalizer;
129
import com.intellij.util.io.EnumeratorStringDescriptor;
1310
import com.intellij.util.io.KeyDescriptor;
11+
import com.jetbrains.php.codeInsight.controlFlow.PhpInstructionProcessor;
12+
import com.jetbrains.php.codeInsight.controlFlow.instructions.PhpAccessVariableInstruction;
13+
import com.jetbrains.php.codeInsight.controlFlow.instructions.PhpInstruction;
1414
import com.jetbrains.php.lang.PhpFileType;
1515
import com.jetbrains.php.lang.psi.PhpFile;
16-
import com.jetbrains.php.lang.psi.elements.*;
16+
import com.jetbrains.php.lang.psi.elements.Method;
17+
import com.jetbrains.php.lang.psi.elements.MethodReference;
18+
import com.jetbrains.php.lang.psi.elements.Parameter;
19+
import com.jetbrains.php.lang.psi.elements.PhpClass;
1720
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
1821
import fr.adrienbrault.idea.symfony2plugin.dic.container.dict.ContainerBuilderCall;
1922
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.externalizer.ObjectStreamDataExternalizer;
2023
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
2124
import gnu.trove.THashMap;
25+
import one.util.streamex.StreamEx;
2226
import org.apache.commons.lang.StringUtils;
2327
import org.jetbrains.annotations.NotNull;
2428

@@ -69,8 +73,10 @@ public DataIndexer<String, ContainerBuilderCall, FileContent> getIndexer() {
6973
return map;
7074
}
7175

72-
psiFile.accept(new MyPsiRecursiveElementWalkingVisitor(map));
73-
76+
StreamEx.of(((PhpFile) psiFile).getTopLevelDefs().values())
77+
.select(PhpClass.class)
78+
.flatMap(clazz -> StreamEx.of(clazz.getOwnMethods()))
79+
.forEach(method -> processMethod(method, map));
7480
return map;
7581
};
7682
}
@@ -130,89 +136,52 @@ private static boolean isValidForIndex(FileContent inputData, PsiFile psiFile) {
130136
return true;
131137
}
132138

133-
private class MyPsiRecursiveElementWalkingVisitor extends PsiRecursiveElementVisitor {
134-
135-
private final Map<String, ContainerBuilderCall> map;
136-
137-
MyPsiRecursiveElementWalkingVisitor(@NotNull Map<String, ContainerBuilderCall> map) {
138-
this.map = map;
139-
}
140-
141-
@Override
142-
public void visitElement(PsiElement element) {
143-
if(!(element instanceof Parameter)) {
144-
super.visitElement(element);
145-
return;
146-
}
147-
148-
ClassReference classReference = ObjectUtils.tryCast(element.getFirstChild(), ClassReference.class);
149-
if(classReference == null) {
150-
return;
151-
}
152-
153-
String fqn = StringUtils.stripStart(classReference.getFQN(), "\\");
154-
if(!SET.contains(fqn)) {
155-
return;
156-
}
157-
158-
Parameter parentOfType = PsiTreeUtil.getParentOfType(classReference, Parameter.class);
159-
if(parentOfType == null) {
160-
return;
161-
}
162-
163-
final String name = parentOfType.getName();
164-
165-
Method method = PsiTreeUtil.getParentOfType(classReference, Method.class);
166-
if(method == null) {
167-
return;
168-
}
169-
170-
method.accept(new MyMethodVariableVisitor(name, map));
171-
172-
super.visitElement(element);
139+
private void processMethod(@NotNull Method method, @NotNull Map<String, ContainerBuilderCall> map) {
140+
Set<CharSequence> containerParameters = StreamEx.of(method.getParameters())
141+
.filter(ContainerBuilderStubIndex::isContainerParam)
142+
.map(Parameter::getNameCS)
143+
.toSet();
144+
if (containerParameters.isEmpty()) return;
145+
MyInstructionProcessor processor = new MyInstructionProcessor(map, containerParameters);
146+
for (PhpInstruction instruction : method.getControlFlow().getInstructions()) {
147+
instruction.process(processor);
173148
}
174149
}
175150

176-
private class MyMethodVariableVisitor extends PsiRecursiveElementVisitor {
151+
private static boolean isContainerParam(@NotNull Parameter parameter) {
152+
String parameterType = parameter.getDeclaredType().toString();
153+
return SET.contains(StringUtils.stripStart(parameterType, "\\"));
154+
}
177155

156+
private static class MyInstructionProcessor extends PhpInstructionProcessor {
178157
@NotNull
179-
private final String name;
180-
158+
private final Map<String, ContainerBuilderCall> map;
181159
@NotNull
182-
private final Map<String, ContainerBuilderCall> result;
160+
private final Set<CharSequence> containerParameters;
183161

184-
MyMethodVariableVisitor(@NotNull String name, @NotNull Map<String, ContainerBuilderCall> result) {
185-
this.name = name;
186-
this.result = result;
162+
MyInstructionProcessor(@NotNull Map<String, ContainerBuilderCall> map,
163+
@NotNull Set<CharSequence> containerParameters) {
164+
this.map = map;
165+
this.containerParameters = containerParameters;
187166
}
188-
167+
189168
@Override
190-
public void visitElement(PsiElement element) {
191-
if(!(element instanceof Variable) || !name.equals(((Variable) element).getName())) {
192-
super.visitElement(element);
193-
return;
194-
}
195-
196-
MethodReference methodReference = ObjectUtils.tryCast(element.getParent(), MethodReference.class);
197-
if(methodReference == null || !METHODS.contains(methodReference.getName())) {
198-
super.visitElement(element);
199-
return;
200-
}
201-
169+
public boolean processAccessVariableInstruction(PhpAccessVariableInstruction instruction) {
170+
if (!instruction.getAccess().isRead() ||
171+
!containerParameters.contains(instruction.getVariableName())) return true;
172+
173+
MethodReference methodReference =
174+
ObjectUtils.tryCast(instruction.getAnchor().getParent(), MethodReference.class);
175+
if (methodReference == null || !METHODS.contains(methodReference.getName())) return true;
176+
202177
String value = PhpElementsUtil.getFirstArgumentStringValue(methodReference);
203-
if(value == null) {
204-
super.visitElement(element);
205-
return;
206-
}
207-
178+
if (value == null) return true;
179+
208180
String methodName = methodReference.getName();
209-
if(!result.containsKey(methodName)) {
210-
result.put(methodName, new ContainerBuilderCall());
211-
}
212-
213-
result.get(methodName).addParameter(value);
214-
215-
super.visitElement(element);
181+
map.computeIfAbsent(methodName, name -> new ContainerBuilderCall());
182+
map.get(methodName).addParameter(value);
183+
184+
return true;
216185
}
217186
}
218187
}

0 commit comments

Comments
 (0)