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;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user