Optimized reading external annotations: now they when annotations file is accessed, it's parsed data is stored in cache.
This commit is contained in:
+69
-44
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.jet.lang.resolve.java.extAnnotations;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.io.StreamUtil;
|
||||
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.containers.ConcurrentWeakHashMap;
|
||||
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.Element;
|
||||
import org.jdom.JDOMException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@@ -49,6 +47,8 @@ import java.util.concurrent.ConcurrentMap;
|
||||
*/
|
||||
@Deprecated
|
||||
public class CoreAnnotationsProvider extends ExternalAnnotationsProvider {
|
||||
static int loadDocumentCount = 0;
|
||||
|
||||
static {
|
||||
// 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");
|
||||
@@ -135,66 +135,81 @@ public class CoreAnnotationsProvider extends ExternalAnnotationsProvider {
|
||||
externalAnnotationsRoots.add(externalAnnotationsRoot);
|
||||
}
|
||||
|
||||
private Map<String, PsiAnnotation> doCollect(@NotNull PsiModifierListOwner listOwner) {
|
||||
final List<PsiFile> files = findExternalAnnotationsFiles(listOwner);
|
||||
if (files == null) {
|
||||
return Collections.emptyMap();
|
||||
private Map<PsiFile, MultiMap<String, AnnotationData>> annotationsFileToData = new HashMap<PsiFile, MultiMap<String, AnnotationData>>();
|
||||
private Map<PsiFile, Long> annotationsFileToModificationStamp = new HashMap<PsiFile, Long>();
|
||||
@NotNull
|
||||
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>();
|
||||
for (PsiFile file : files) {
|
||||
if (!file.isValid()) continue;
|
||||
final Document document;
|
||||
else {
|
||||
MultiMap<String, AnnotationData> data = new MultiMap<String, AnnotationData>();
|
||||
annotationsFileToData.put(file, data);
|
||||
annotationsFileToModificationStamp.put(file, file.getModificationStamp());
|
||||
|
||||
Document document;
|
||||
try {
|
||||
// CoreLocalVirtualFile.getInputStream() fails with AssertionError
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
InputStream stream = "CoreLocalVirtualFile".equals(virtualFile.getClass().getSimpleName())
|
||||
? new BufferedInputStream(new FileInputStream(virtualFile.getPath()))
|
||||
: virtualFile.getInputStream();
|
||||
document = JDOMUtil.loadDocument(escapeAttributes(StreamUtil.readText(stream)));
|
||||
//noinspection ConstantConditions
|
||||
System.out.println("loadDocument count = " + (loadDocumentCount++));
|
||||
document = JDOMUtil.loadDocument(escapeAttributes(StreamUtil.readText(file.getVirtualFile().getInputStream())));
|
||||
}
|
||||
catch (IOException e) {
|
||||
|
||||
LOG.error(e);
|
||||
continue;
|
||||
return data;
|
||||
}
|
||||
catch (JDOMException e) {
|
||||
LOG.error(e);
|
||||
continue;
|
||||
return data;
|
||||
}
|
||||
if (document == null) continue;
|
||||
final Element rootElement = document.getRootElement();
|
||||
if (rootElement == null) continue;
|
||||
final String externalName = getExternalName(listOwner, false);
|
||||
final String oldExternalName = getNormalizedExternalName(listOwner);
|
||||
Element rootElement = document.getRootElement();
|
||||
if (rootElement == null) return data;
|
||||
|
||||
//noinspection unchecked
|
||||
for (final Element element : (List<Element>) rootElement.getChildren()) {
|
||||
final String className = element.getAttributeValue("name");
|
||||
if (!Comparing.strEqual(className, externalName) && !Comparing.strEqual(className, oldExternalName)) {
|
||||
continue;
|
||||
}
|
||||
for (Element element : (List<Element>) rootElement.getChildren()) {
|
||||
String ownerName = element.getAttributeValue("name");
|
||||
if (ownerName == null) continue;
|
||||
//noinspection unchecked
|
||||
for (Element annotationElement : (List<Element>) element.getChildren()) {
|
||||
final String annotationFQN = annotationElement.getAttributeValue("name");
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
String annotationFQN = annotationElement.getAttributeValue("name");
|
||||
StringBuilder buf = new StringBuilder();
|
||||
//noinspection unchecked
|
||||
for (Element annotationParameter : (List<Element>) annotationElement.getChildren()) {
|
||||
buf.append(",");
|
||||
final String nameValue = annotationParameter.getAttributeValue("name");
|
||||
String nameValue = annotationParameter.getAttributeValue("name");
|
||||
if (nameValue != null) {
|
||||
buf.append(nameValue).append("=");
|
||||
}
|
||||
buf.append(annotationParameter.getAttributeValue("val"));
|
||||
}
|
||||
final String annotationText =
|
||||
"@" + annotationFQN + (buf.length() > 0 ? "(" + StringUtil.trimStart(buf.toString(), ",") + ")" : "");
|
||||
try {
|
||||
result.put(annotationFQN,
|
||||
JavaPsiFacade.getInstance(listOwner.getProject()).getElementFactory().createAnnotationFromText(
|
||||
annotationText, null));
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
String annotationText = "@" + annotationFQN + (buf.length() > 0 ? "(" + StringUtil.trimStart(buf.toString(), ",") + ")" : "");
|
||||
data.putValue(ownerName, new AnnotationData(annotationFQN, annotationText));
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
private static class AnnotationData {
|
||||
public String annotationClassFqName;
|
||||
public String annotationText;
|
||||
|
||||
private AnnotationData(String annotationClassFqName, String annotationText) {
|
||||
this.annotationClassFqName = annotationClassFqName;
|
||||
this.annotationText = annotationText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user