Optimized reading external annotations: now they when annotations file is accessed, it's parsed data is stored in cache.

This commit is contained in:
Evgeny Gerashchenko
2012-07-31 20:15:52 +04:00
parent dcd5cad427
commit 7370107616
@@ -17,7 +17,6 @@
package org.jetbrains.jet.lang.resolve.java.extAnnotations; package org.jetbrains.jet.lang.resolve.java.extAnnotations;
import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
@@ -28,16 +27,15 @@ import com.intellij.util.IncorrectOperationException;
import com.intellij.util.StringBuilderSpinAllocator; import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.util.containers.ConcurrentWeakHashMap; import com.intellij.util.containers.ConcurrentWeakHashMap;
import com.intellij.util.containers.ConcurrentWeakValueHashMap; import com.intellij.util.containers.ConcurrentWeakValueHashMap;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jdom.Document; import org.jdom.Document;
import org.jdom.Element; import org.jdom.Element;
import org.jdom.JDOMException; import org.jdom.JDOMException;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
@@ -49,6 +47,8 @@ import java.util.concurrent.ConcurrentMap;
*/ */
@Deprecated @Deprecated
public class CoreAnnotationsProvider extends ExternalAnnotationsProvider { public class CoreAnnotationsProvider extends ExternalAnnotationsProvider {
static int loadDocumentCount = 0;
static { static {
// This is an ugly workaround for JDOM 1.1 used from application started from Ant 1.8 without forking // This is an ugly workaround for JDOM 1.1 used from application started from Ant 1.8 without forking
System.setProperty("javax.xml.parsers.SAXParserFactory", "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"); System.setProperty("javax.xml.parsers.SAXParserFactory", "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
@@ -135,66 +135,81 @@ public class CoreAnnotationsProvider extends ExternalAnnotationsProvider {
externalAnnotationsRoots.add(externalAnnotationsRoot); externalAnnotationsRoots.add(externalAnnotationsRoot);
} }
private Map<String, PsiAnnotation> doCollect(@NotNull PsiModifierListOwner listOwner) { private Map<PsiFile, MultiMap<String, AnnotationData>> annotationsFileToData = new HashMap<PsiFile, MultiMap<String, AnnotationData>>();
final List<PsiFile> files = findExternalAnnotationsFiles(listOwner); private Map<PsiFile, Long> annotationsFileToModificationStamp = new HashMap<PsiFile, Long>();
if (files == null) { @NotNull
return Collections.emptyMap(); private MultiMap<String, AnnotationData> getDataFromFile(@NotNull PsiFile file) {
if (annotationsFileToData.containsKey(file) && file.getModificationStamp() == annotationsFileToModificationStamp.get(file)) {
return annotationsFileToData.get(file);
} }
final Map<String, PsiAnnotation> result = new HashMap<String, PsiAnnotation>(); else {
for (PsiFile file : files) { MultiMap<String, AnnotationData> data = new MultiMap<String, AnnotationData>();
if (!file.isValid()) continue; annotationsFileToData.put(file, data);
final Document document; annotationsFileToModificationStamp.put(file, file.getModificationStamp());
Document document;
try { try {
// CoreLocalVirtualFile.getInputStream() fails with AssertionError //noinspection ConstantConditions
VirtualFile virtualFile = file.getVirtualFile(); System.out.println("loadDocument count = " + (loadDocumentCount++));
InputStream stream = "CoreLocalVirtualFile".equals(virtualFile.getClass().getSimpleName()) document = JDOMUtil.loadDocument(escapeAttributes(StreamUtil.readText(file.getVirtualFile().getInputStream())));
? new BufferedInputStream(new FileInputStream(virtualFile.getPath()))
: virtualFile.getInputStream();
document = JDOMUtil.loadDocument(escapeAttributes(StreamUtil.readText(stream)));
} }
catch (IOException e) { catch (IOException e) {
LOG.error(e); LOG.error(e);
continue; return data;
} }
catch (JDOMException e) { catch (JDOMException e) {
LOG.error(e); LOG.error(e);
continue; return data;
} }
if (document == null) continue; Element rootElement = document.getRootElement();
final Element rootElement = document.getRootElement(); if (rootElement == null) return data;
if (rootElement == null) continue;
final String externalName = getExternalName(listOwner, false);
final String oldExternalName = getNormalizedExternalName(listOwner);
//noinspection unchecked //noinspection unchecked
for (final Element element : (List<Element>) rootElement.getChildren()) { for (Element element : (List<Element>) rootElement.getChildren()) {
final String className = element.getAttributeValue("name"); String ownerName = element.getAttributeValue("name");
if (!Comparing.strEqual(className, externalName) && !Comparing.strEqual(className, oldExternalName)) { if (ownerName == null) continue;
continue;
}
//noinspection unchecked //noinspection unchecked
for (Element annotationElement : (List<Element>) element.getChildren()) { for (Element annotationElement : (List<Element>) element.getChildren()) {
final String annotationFQN = annotationElement.getAttributeValue("name"); String annotationFQN = annotationElement.getAttributeValue("name");
final StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
//noinspection unchecked //noinspection unchecked
for (Element annotationParameter : (List<Element>) annotationElement.getChildren()) { for (Element annotationParameter : (List<Element>) annotationElement.getChildren()) {
buf.append(","); buf.append(",");
final String nameValue = annotationParameter.getAttributeValue("name"); String nameValue = annotationParameter.getAttributeValue("name");
if (nameValue != null) { if (nameValue != null) {
buf.append(nameValue).append("="); buf.append(nameValue).append("=");
} }
buf.append(annotationParameter.getAttributeValue("val")); buf.append(annotationParameter.getAttributeValue("val"));
} }
final String annotationText = String annotationText = "@" + annotationFQN + (buf.length() > 0 ? "(" + StringUtil.trimStart(buf.toString(), ",") + ")" : "");
"@" + annotationFQN + (buf.length() > 0 ? "(" + StringUtil.trimStart(buf.toString(), ",") + ")" : ""); data.putValue(ownerName, new AnnotationData(annotationFQN, annotationText));
try { }
result.put(annotationFQN, }
JavaPsiFacade.getInstance(listOwner.getProject()).getElementFactory().createAnnotationFromText(
annotationText, null)); return data;
} }
catch (IncorrectOperationException e) { }
LOG.error(e);
} private Map<String, PsiAnnotation> doCollect(@NotNull PsiModifierListOwner listOwner) {
final List<PsiFile> files = findExternalAnnotationsFiles(listOwner);
if (files == null) {
return Collections.emptyMap();
}
Map<String, PsiAnnotation> result = new HashMap<String, PsiAnnotation>();
String externalName = getExternalName(listOwner, false);
String oldExternalName = getNormalizedExternalName(listOwner);
for (PsiFile file : files) {
if (!file.isValid()) continue;
MultiMap<String, AnnotationData> fileData = getDataFromFile(file);
for (AnnotationData annotationData : ContainerUtil.concat(fileData.get(externalName), fileData.get(oldExternalName))) {
try {
result.put(annotationData.annotationClassFqName,
JavaPsiFacade.getInstance(listOwner.getProject()).getElementFactory().createAnnotationFromText(
annotationData.annotationText, null));
}
catch (IncorrectOperationException e) {
LOG.error(e);
} }
} }
} }
@@ -291,4 +306,14 @@ public class CoreAnnotationsProvider extends ExternalAnnotationsProvider {
} }
return sb.toString(); return sb.toString();
} }
private static class AnnotationData {
public String annotationClassFqName;
public String annotationText;
private AnnotationData(String annotationClassFqName, String annotationText) {
this.annotationClassFqName = annotationClassFqName;
this.annotationText = annotationText;
}
}
} }