Skip to content

Commit 4803d3c

Browse files
committed
complete refactoring of template related stuff for massive performance and memory improvements; only use VirtualFile object and convert them later to PsiFile; also fixing cache of overwrite/implements twig linemarker #321
1 parent 9bcd28c commit 4803d3c

15 files changed

+159
-118
lines changed

src/fr/adrienbrault/idea/symfony2plugin/TwigHelper.java

+49-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fr.adrienbrault.idea.symfony2plugin;
22

3+
import com.intellij.codeInsight.lookup.LookupElement;
34
import com.intellij.openapi.project.Project;
45
import com.intellij.openapi.vfs.VfsUtil;
56
import com.intellij.openapi.vfs.VirtualFile;
@@ -25,6 +26,7 @@
2526
import fr.adrienbrault.idea.symfony2plugin.asset.dic.AssetFile;
2627
import fr.adrienbrault.idea.symfony2plugin.stubs.SymfonyProcessors;
2728
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.TwigMacroFunctionStubIndex;
29+
import fr.adrienbrault.idea.symfony2plugin.templating.TemplateLookupElement;
2830
import fr.adrienbrault.idea.symfony2plugin.templating.path.*;
2931
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigTypeResolveUtil;
3032
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
@@ -49,10 +51,11 @@ public class TwigHelper {
4951

5052
public static String TEMPLATE_ANNOTATION_CLASS = "\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Template";
5153

52-
synchronized public static Map<String, PsiFile> getTemplateFilesByName(Project project, boolean useTwig, boolean usePhp) {
53-
Map<String, PsiFile> results = new HashMap<String, PsiFile>();
54+
public static Map<String, VirtualFile> getTemplateFilesByName(Project project, boolean useTwig, boolean usePhp) {
5455

55-
ArrayList<TwigPath> twigPaths = new ArrayList<TwigPath>();
56+
Map<String, VirtualFile> results = new HashMap<String, VirtualFile>();
57+
58+
List<TwigPath> twigPaths = new ArrayList<TwigPath>();
5659
twigPaths.addAll(getTwigNamespaces(project));
5760

5861
if(twigPaths.size() == 0) {
@@ -82,18 +85,11 @@ public boolean visitFile(@NotNull VirtualFile virtualFile) {
8285
return results;
8386
}
8487

85-
synchronized public static Map<String, TwigFile> getTwigFilesByName(Project project) {
86-
Map<String, TwigFile> results = new HashMap<String, TwigFile>();
87-
for(Map.Entry<String, PsiFile> entry: getTemplateFilesByName(project, true, true).entrySet()) {
88-
if(entry.getValue() instanceof TwigFile) {
89-
results.put(entry.getKey(), (TwigFile) entry.getValue());
90-
}
91-
}
92-
93-
return results;
88+
public static Map<String, VirtualFile> getTwigFilesByName(Project project) {
89+
return getTemplateFilesByName(project, true, false);
9490
}
9591

96-
synchronized public static Map<String, PsiFile> getTemplateFilesByName(Project project) {
92+
public static Map<String, VirtualFile> getTemplateFilesByName(Project project) {
9793
return getTemplateFilesByName(project, true, true);
9894
}
9995

@@ -175,20 +171,27 @@ public static PsiElement[] getTemplatePsiElements(Project project, String templa
175171

176172
String normalizedTemplateName = normalizeTemplateName(templateName);
177173

178-
Map<String, PsiFile> twigFiles = TwigHelper.getTemplateFilesByName(project);
174+
Map<String, VirtualFile> twigFiles = TwigHelper.getTemplateFilesByName(project);
179175
if(!twigFiles.containsKey(normalizedTemplateName)) {
180176
return new PsiElement[0];
181177
}
182178

183-
return new PsiElement[] {twigFiles.get(normalizedTemplateName)};
179+
VirtualFile virtualFile = twigFiles.get(normalizedTemplateName);
180+
181+
PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
182+
if(psiFile != null) {
183+
return new PsiElement[] {psiFile};
184+
}
185+
186+
return new PsiElement[0];
184187
}
185188

186-
synchronized public static ArrayList<TwigPath> getTwigNamespaces(Project project) {
189+
public static List<TwigPath> getTwigNamespaces(Project project) {
187190
return getTwigNamespaces(project, true);
188191
}
189192

190-
synchronized public static ArrayList<TwigPath> getTwigNamespaces(Project project, boolean includeSettings) {
191-
ArrayList<TwigPath> twigPaths = new ArrayList<TwigPath>();
193+
public static List<TwigPath> getTwigNamespaces(Project project, boolean includeSettings) {
194+
List<TwigPath> twigPaths = new ArrayList<TwigPath>();
192195
PhpIndex phpIndex = PhpIndex.getInstance(project);
193196

194197
TwigPathServiceParser twigPathServiceParser = ServiceXmlParserFactory.getInstance(project, TwigPathServiceParser.class);
@@ -219,7 +222,7 @@ synchronized public static ArrayList<TwigPath> getTwigNamespaces(Project project
219222
return twigPaths;
220223
}
221224

222-
ArrayList<TwigNamespaceSetting> twigNamespaceSettings = (ArrayList<TwigNamespaceSetting>) Settings.getInstance(project).twigNamespaces;
225+
List<TwigNamespaceSetting> twigNamespaceSettings = Settings.getInstance(project).twigNamespaces;
223226
if(twigNamespaceSettings != null) {
224227
for(TwigNamespaceSetting twigNamespaceSetting: twigNamespaceSettings) {
225228
if(twigNamespaceSetting.isCustom()) {
@@ -835,4 +838,31 @@ public boolean execute(@NotNull PsiElement psiElement) {
835838
return targets;
836839
}
837840

841+
public static Collection<LookupElement> getTwigLookupElements(Project project) {
842+
VirtualFile baseDir = project.getBaseDir();
843+
844+
Collection<LookupElement> lookupElements = new ArrayList<LookupElement>();
845+
846+
for (Map.Entry<String, VirtualFile> entry : TwigHelper.getTwigFilesByName(project).entrySet()) {
847+
lookupElements.add(
848+
new TemplateLookupElement(entry.getKey(), entry.getValue(), baseDir)
849+
);
850+
}
851+
852+
return lookupElements;
853+
}
854+
855+
public static Collection<LookupElement> getAllTemplateLookupElements(Project project) {
856+
VirtualFile baseDir = project.getBaseDir();
857+
858+
Collection<LookupElement> lookupElements = new ArrayList<LookupElement>();
859+
860+
for (Map.Entry<String, VirtualFile> entry : TwigHelper.getTemplateFilesByName(project).entrySet()) {
861+
lookupElements.add(
862+
new TemplateLookupElement(entry.getKey(), entry.getValue(), baseDir)
863+
);
864+
}
865+
866+
return lookupElements;
867+
}
838868
}

src/fr/adrienbrault/idea/symfony2plugin/action/SymfonySymbolSearchAction.java

+10-5
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
import com.intellij.openapi.fileTypes.FileType;
1313
import com.intellij.openapi.project.DumbAware;
1414
import com.intellij.openapi.project.Project;
15+
import com.intellij.openapi.vfs.VirtualFile;
1516
import com.intellij.psi.PsiElement;
1617
import com.intellij.psi.PsiFile;
18+
import com.intellij.psi.PsiManager;
1719
import com.intellij.psi.search.GlobalSearchScope;
1820
import com.intellij.util.Processor;
1921
import com.intellij.util.indexing.FindSymbolParameters;
@@ -71,7 +73,7 @@ private static class Symfony2NavigationContributor implements ChooseByNameContri
7173

7274
final private Project project;
7375
private ContainerCollectionResolver.ServiceCollector serviceCollector;
74-
private Map<String, PsiFile> templateMap;
76+
private Map<String, VirtualFile> templateMap;
7577
private Map<String, Route> routes;
7678
private Set<String> twigMacroSet;
7779
private Map<String, LookupElement> lookupElements;
@@ -91,7 +93,7 @@ private ContainerCollectionResolver.ServiceCollector getServiceCollector() {
9193
return this.serviceCollector;
9294
}
9395

94-
private Map<String, PsiFile> getTemplateMap() {
96+
private Map<String, VirtualFile> getTemplateMap() {
9597

9698
if(this.templateMap == null) {
9799
this.templateMap = TwigHelper.getTemplateFilesByName(this.project, true, true);
@@ -142,7 +144,7 @@ public void processNames(@NotNull Processor<String> processor, @NotNull GlobalSe
142144
processor.process(name);
143145
}
144146

145-
for(Map.Entry<String, PsiFile> entry: getTemplateMap().entrySet()) {
147+
for(Map.Entry<String, VirtualFile> entry: getTemplateMap().entrySet()) {
146148
processor.process(entry.getKey());
147149
}
148150

@@ -178,8 +180,11 @@ public void processElementsWithName(@NotNull String name, @NotNull Processor<Nav
178180
}
179181

180182
if(getTemplateMap().containsKey(name)) {
181-
PsiFile psiFile = getTemplateMap().get(name);
182-
processor.process(new NavigationItemEx(psiFile, name, psiFile.getFileType().getIcon(), "Template"));
183+
VirtualFile virtualFile = getTemplateMap().get(name);
184+
PsiFile psiFile = PsiManager.getInstance(this.project).findFile(virtualFile);
185+
if(psiFile != null) {
186+
processor.process(new NavigationItemEx(psiFile, name, psiFile.getFileType().getIcon(), "Template"));
187+
}
183188
}
184189

185190
if(getRoutes().containsKey(name)) {

src/fr/adrienbrault/idea/symfony2plugin/navigation/TemplateFileContributor.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.intellij.navigation.ChooseByNameContributor;
44
import com.intellij.navigation.NavigationItem;
55
import com.intellij.openapi.project.Project;
6+
import com.intellij.openapi.vfs.VirtualFile;
67
import com.intellij.psi.PsiFile;
78
import com.jetbrains.twig.TwigFile;
89
import fr.adrienbrault.idea.symfony2plugin.TwigHelper;
@@ -17,7 +18,7 @@ public class TemplateFileContributor implements ChooseByNameContributor {
1718
@NotNull
1819
@Override
1920
public String[] getNames(Project project, boolean b) {
20-
Map<String, TwigFile> psiElements = TwigHelper.getTwigFilesByName(project);
21+
Map<String, VirtualFile> psiElements = TwigHelper.getTwigFilesByName(project);
2122
Set<String> sets = psiElements.keySet();
2223
return sets.toArray(new String[sets.size()]);
2324
}

src/fr/adrienbrault/idea/symfony2plugin/templating/TemplateLookupElement.java

+15-17
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.intellij.codeInsight.lookup.LookupElementPresentation;
77
import com.intellij.openapi.util.Iconable;
88
import com.intellij.openapi.vfs.VfsUtil;
9+
import com.intellij.openapi.vfs.VirtualFile;
910
import com.intellij.psi.PsiElement;
1011
import com.intellij.psi.PsiFile;
1112
import com.jetbrains.twig.TwigFile;
@@ -17,28 +18,30 @@
1718
*/
1819
public class TemplateLookupElement extends LookupElement {
1920

20-
private String templateName;
21-
private PsiFile twigFile;
22-
private PsiElement psiElement = null;
21+
private final VirtualFile virtualFile;
22+
private final VirtualFile projectBaseDir;
23+
24+
private final String templateName;
25+
2326

2427
@Nullable
2528
private InsertHandler<LookupElement> insertHandler = null;
2629

2730
@Deprecated
28-
public TemplateLookupElement(String templateName, TwigFile twigFile) {
31+
public TemplateLookupElement(@NotNull String templateName, TwigFile twigFile) {
2932
this(templateName, (PsiFile) twigFile);
3033
}
3134

32-
public TemplateLookupElement(String templateName, PsiFile psiFile) {
35+
public TemplateLookupElement(@NotNull String templateName, @NotNull PsiFile psiFile) {
3336
this.templateName = templateName;
34-
this.twigFile = psiFile;
37+
this.virtualFile = psiFile.getVirtualFile();
38+
this.projectBaseDir = psiFile.getProject().getBaseDir();
3539
}
3640

37-
public TemplateLookupElement(String templateName, PsiFile twigFile, PsiElement psiElement, InsertHandler<LookupElement> insertHandler) {
41+
public TemplateLookupElement(@NotNull String templateName, @NotNull VirtualFile virtualFile, @NotNull VirtualFile projectBaseDir) {
3842
this.templateName = templateName;
39-
this.twigFile = twigFile;
40-
this.insertHandler = insertHandler;
41-
this.psiElement = psiElement;
43+
this.virtualFile = virtualFile;
44+
this.projectBaseDir = projectBaseDir;
4245
}
4346

4447
@NotNull
@@ -47,11 +50,6 @@ public String getLookupString() {
4750
return templateName;
4851
}
4952

50-
@NotNull
51-
public Object getObject() {
52-
return this.psiElement != null ? this.psiElement : super.getObject();
53-
}
54-
5553
public void handleInsert(InsertionContext context) {
5654
if (this.insertHandler != null) {
5755
this.insertHandler.handleInsert(context, this);
@@ -60,8 +58,8 @@ public void handleInsert(InsertionContext context) {
6058

6159
public void renderElement(LookupElementPresentation presentation) {
6260
presentation.setItemText(getLookupString());
63-
presentation.setIcon(this.twigFile.getIcon(Iconable.ICON_FLAG_VISIBILITY));
64-
presentation.setTypeText(VfsUtil.getRelativePath(twigFile.getContainingDirectory().getVirtualFile(), twigFile.getProject().getBaseDir(), '/'));
61+
presentation.setIcon(this.virtualFile.getFileType().getIcon());
62+
presentation.setTypeText(VfsUtil.getRelativePath(this.virtualFile, this.projectBaseDir, '/'));
6563
presentation.setTypeGrayed(true);
6664
}
6765

src/fr/adrienbrault/idea/symfony2plugin/templating/TemplateReference.java

+2-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fr.adrienbrault.idea.symfony2plugin.templating;
22

33
import com.intellij.codeInsight.lookup.LookupElement;
4+
import com.intellij.openapi.vfs.VirtualFile;
45
import com.intellij.psi.*;
56
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
67
import fr.adrienbrault.idea.symfony2plugin.TwigHelper;
@@ -25,16 +26,7 @@ public TemplateReference(@NotNull StringLiteralExpression element) {
2526
@NotNull
2627
@Override
2728
public Object[] getVariants() {
28-
List<LookupElement> results = new ArrayList<LookupElement>();
29-
30-
Map<String, PsiFile> PsiFileMap = TwigHelper.getTemplateFilesByName(getElement().getProject());
31-
for (Map.Entry<String, PsiFile> entry : PsiFileMap.entrySet()) {
32-
results.add(
33-
new TemplateLookupElement(entry.getKey(), entry.getValue())
34-
);
35-
}
36-
37-
return results.toArray();
29+
return TwigHelper.getAllTemplateLookupElements(getElement().getProject()).toArray();
3830
}
3931

4032
@NotNull

src/fr/adrienbrault/idea/symfony2plugin/templating/TwigControllerLineMarkerProvider.java

+12-12
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
public class TwigControllerLineMarkerProvider implements LineMarkerProvider {
3737

3838

39-
private Map<String, PsiFile> templateMapCache = null;
39+
private Map<String, VirtualFile> templateMapCache = null;
4040

4141
@Override
4242
public void collectSlowLineMarkers(@NotNull List<PsiElement> psiElements, @NotNull Collection<LineMarkerInfo> results) {
@@ -100,7 +100,7 @@ private LineMarkerInfo attachIncludes(TwigFile twigFile) {
100100

101101

102102
final Collection<PsiFile> targets = new ArrayList<PsiFile>();
103-
for(Map.Entry<String, PsiFile> entry: TwigUtil.getTemplateName(twigFile).entrySet()) {
103+
for(Map.Entry<String, VirtualFile> entry: TwigUtil.getTemplateName(twigFile).entrySet()) {
104104

105105
final Project project = twigFile.getProject();
106106
FileBasedIndexImpl.getInstance().getFilesWithKey(TwigIncludeStubIndex.KEY, new HashSet<String>(Arrays.asList(entry.getKey())), new Processor<VirtualFile>() {
@@ -122,7 +122,7 @@ public boolean process(VirtualFile virtualFile) {
122122
return null;
123123
}
124124

125-
Map<String, PsiFile> files = getTemplateFilesByName(twigFile.getProject());
125+
Map<String, VirtualFile> files = getTemplateFilesByName(twigFile.getProject());
126126

127127
List<GotoRelatedItem> gotoRelatedItems = new ArrayList<GotoRelatedItem>();
128128
for(PsiElement blockTag: targets) {
@@ -133,15 +133,15 @@ public boolean process(VirtualFile virtualFile) {
133133

134134
}
135135

136-
private Map<String, PsiFile> getTemplateFilesByName(Project project) {
137-
return this.templateMapCache == null ? TwigHelper.getTemplateFilesByName(project, true, false) : this.templateMapCache;
136+
private Map<String, VirtualFile> getTemplateFilesByName(Project project) {
137+
return this.templateMapCache == null ? this.templateMapCache = TwigHelper.getTemplateFilesByName(project, true, false) : this.templateMapCache;
138138
}
139139

140140
@Nullable
141141
private LineMarkerInfo attachFromIncludes(TwigFile twigFile) {
142142

143143
final Collection<PsiFile> targets = new ArrayList<PsiFile>();
144-
for(Map.Entry<String, PsiFile> entry: TwigUtil.getTemplateName(twigFile).entrySet()) {
144+
for(Map.Entry<String, VirtualFile> entry: TwigUtil.getTemplateName(twigFile).entrySet()) {
145145

146146
final Project project = twigFile.getProject();
147147
FileBasedIndexImpl.getInstance().getFilesWithKey(TwigMacroFromStubIndex.KEY, new HashSet<String>(Arrays.asList(entry.getKey())), new Processor<VirtualFile>() {
@@ -163,7 +163,7 @@ public boolean process(VirtualFile virtualFile) {
163163
return null;
164164
}
165165

166-
Map<String, PsiFile> files = getTemplateFilesByName(twigFile.getProject());
166+
Map<String, VirtualFile> files = getTemplateFilesByName(twigFile.getProject());
167167

168168
List<GotoRelatedItem> gotoRelatedItems = new ArrayList<GotoRelatedItem>();
169169
for(PsiElement blockTag: targets) {
@@ -195,7 +195,7 @@ private LineMarkerInfo attachBlockImplements(final PsiElement psiElement) {
195195
return null;
196196
}
197197

198-
Map<String, PsiFile> files = getTemplateFilesByName(psiElement.getProject());
198+
Map<String, VirtualFile> files = getTemplateFilesByName(psiElement.getProject());
199199

200200
List<PsiFile> twigChild = new ArrayList<PsiFile>();
201201
getTwigChildList(files, psiFile, twigChild, 8);
@@ -239,7 +239,7 @@ private LineMarkerInfo attachBlockOverwrites(PsiElement psiElement) {
239239
return null;
240240
}
241241

242-
Map<String, PsiFile> files = getTemplateFilesByName(psiElement.getProject());
242+
Map<String, VirtualFile> files = getTemplateFilesByName(psiElement.getProject());
243243

244244
List<GotoRelatedItem> gotoRelatedItems = new ArrayList<GotoRelatedItem>();
245245
for(PsiElement blockTag: blocks) {
@@ -264,7 +264,7 @@ public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement psiElement) {
264264
return null;
265265
}
266266

267-
private static void getTwigChildList(Map<String, PsiFile> files, final PsiFile psiFile, final List<PsiFile> twigChild, int depth) {
267+
private static void getTwigChildList(Map<String, VirtualFile> files, final PsiFile psiFile, final List<PsiFile> twigChild, int depth) {
268268

269269
if(depth <= 0) {
270270
return;
@@ -273,10 +273,10 @@ private static void getTwigChildList(Map<String, PsiFile> files, final PsiFile p
273273
// use set here, we have multiple shortcut on one file, but only one is required
274274
final HashSet<VirtualFile> virtualFiles = new LinkedHashSet<VirtualFile>();
275275

276-
for(Map.Entry<String, PsiFile> entry: files.entrySet()) {
276+
for(Map.Entry<String, VirtualFile> entry: files.entrySet()) {
277277

278278
// getFilesWithKey dont support keyset with > 1 items (bug?), so we cant merge calls
279-
if(entry.getValue().equals(psiFile)) {
279+
if(entry.getValue().equals(psiFile.getVirtualFile())) {
280280
String key = entry.getKey();
281281
FileBasedIndexImpl.getInstance().getFilesWithKey(TwigExtendsStubIndex.KEY, new HashSet<String>(Arrays.asList(key)), new Processor<VirtualFile>() {
282282
@Override

0 commit comments

Comments
 (0)