Annotations on lazy classes are resolved lazily

This commit is contained in:
Andrey Breslav
2014-03-30 09:07:43 +04:00
parent b43958f4b3
commit f0bab0c6d1
3 changed files with 53 additions and 36 deletions
@@ -116,7 +116,7 @@ public class AnnotationResolver {
} }
private Annotations resolveAnnotationEntries( private Annotations resolveAnnotationEntries(
@NotNull JetScope scope, @NotNull final JetScope scope,
@NotNull List<JetAnnotationEntry> annotationEntryElements, @NotNull List<JetAnnotationEntry> annotationEntryElements,
@NotNull BindingTrace trace, @NotNull BindingTrace trace,
boolean shouldResolveArguments boolean shouldResolveArguments
@@ -128,15 +128,22 @@ public class AnnotationResolver {
if (descriptor == null) { if (descriptor == null) {
if (TopDownAnalyzer.LAZY) { if (TopDownAnalyzer.LAZY) {
descriptor = new LazyAnnotationDescriptor( descriptor = new LazyAnnotationDescriptor(
new LazyAnnotationsContext(this, storageManager, scope, trace), new LazyAnnotationsContext(this, storageManager, trace) {
@NotNull
@Override
public JetScope getScope() {
return scope;
}
},
entryElement entryElement
); );
} }
else { else {
descriptor = new AnnotationDescriptorImpl(); descriptor = new AnnotationDescriptorImpl();
((AnnotationDescriptorImpl) descriptor).setAnnotationType(resolveAnnotationType(scope, entryElement)); ((AnnotationDescriptorImpl) descriptor).setAnnotationType(resolveAnnotationType(scope, entryElement));
trace.record(BindingContext.ANNOTATION, entryElement, descriptor);
} }
trace.record(BindingContext.ANNOTATION, entryElement, descriptor);
} }
if (shouldResolveArguments) { if (shouldResolveArguments) {
resolveAnnotationArguments(entryElement, scope, trace); resolveAnnotationArguments(entryElement, scope, trace);
@@ -218,7 +225,8 @@ public class AnnotationResolver {
) { ) {
AnnotationDescriptor annotationDescriptor = trace.getBindingContext().get(BindingContext.ANNOTATION, annotationEntry); AnnotationDescriptor annotationDescriptor = trace.getBindingContext().get(BindingContext.ANNOTATION, annotationEntry);
assert annotationDescriptor != null : "Annotation descriptor should be created before resolving arguments for " + annotationEntry.getText(); assert annotationDescriptor != null : "Annotation descriptor should be created before resolving arguments for " + annotationEntry.getText();
if (TopDownAnalyzer.LAZY && annotationDescriptor instanceof LazyAnnotationDescriptor) { if (annotationDescriptor instanceof LazyAnnotationDescriptor) {
// TopDownAnalyzer.LAZY
((LazyAnnotationDescriptor) annotationDescriptor).forceResolveAllContents(); ((LazyAnnotationDescriptor) annotationDescriptor).forceResolveAllContents();
return; return;
} }
@@ -20,30 +20,31 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.jet.lang.resolve.name.FqName import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.lang.descriptors.annotations.Annotations import org.jetbrains.jet.lang.descriptors.annotations.Annotations
import org.jetbrains.jet.lang.resolve.lazy.LazyEntity import org.jetbrains.jet.lang.resolve.lazy.LazyEntity
import org.jetbrains.jet.lang.psi.JetAnnotated
import org.jetbrains.jet.lang.psi.JetAnnotationEntry import org.jetbrains.jet.lang.psi.JetAnnotationEntry
import org.jetbrains.jet.lang.resolve.DescriptorUtils import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.lang.resolve.AnnotationResolver
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant
import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil
import org.jetbrains.jet.storage.StorageManager import org.jetbrains.jet.storage.StorageManager
import org.jetbrains.jet.lang.resolve.scopes.JetScope import org.jetbrains.jet.lang.resolve.AnnotationResolver
import org.jetbrains.jet.lang.resolve.BindingTrace import org.jetbrains.jet.lang.resolve.BindingTrace
import org.jetbrains.jet.lang.resolve.scopes.JetScope
import org.jetbrains.jet.utils.keysToMapExceptNulls import org.jetbrains.jet.utils.keysToMapExceptNulls
import org.jetbrains.jet.lang.resolve.BindingContext
class LazyAnnotationsContext( abstract class LazyAnnotationsContext(
val annotationResolver: AnnotationResolver, val annotationResolver: AnnotationResolver,
val storageManager: StorageManager, val storageManager: StorageManager,
val scope: JetScope,
val trace: BindingTrace val trace: BindingTrace
) ) {
abstract val scope: JetScope
}
public class LazyAnnotations( public class LazyAnnotations(
val c: LazyAnnotationsContext, val c: LazyAnnotationsContext,
val annotatedElement: JetAnnotated val annotationEntries: List<JetAnnotationEntry>
) : Annotations, LazyEntity { ) : Annotations, LazyEntity {
override fun isEmpty() = annotatedElement.getAnnotationEntries().isEmpty() override fun isEmpty() = annotationEntries.isEmpty()
val _annotation = c.storageManager.createMemoizedFunction { val _annotation = c.storageManager.createMemoizedFunction {
(entry: JetAnnotationEntry) -> (entry: JetAnnotationEntry) ->
@@ -69,7 +70,7 @@ public class LazyAnnotations(
} }
override fun iterator(): Iterator<AnnotationDescriptor> { override fun iterator(): Iterator<AnnotationDescriptor> {
return annotatedElement.getAnnotationEntries().stream().map(_annotation).iterator() return annotationEntries.stream().map(_annotation).iterator()
} }
override fun forceResolveAllContents() { override fun forceResolveAllContents() {
@@ -83,6 +84,10 @@ public class LazyAnnotationDescriptor(
val annotationEntry: JetAnnotationEntry val annotationEntry: JetAnnotationEntry
) : AnnotationDescriptor, LazyEntity { ) : AnnotationDescriptor, LazyEntity {
{
c.trace.record(BindingContext.ANNOTATION, annotationEntry, this)
}
private val _resolutionResults = c.storageManager.createLazyValue { private val _resolutionResults = c.storageManager.createLazyValue {
val results = c.annotationResolver.resolveAnnotationCall( val results = c.annotationResolver.resolveAnnotationCall(
annotationEntry, annotationEntry,
@@ -76,7 +76,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
private final ClassKind kind; private final ClassKind kind;
private final boolean isInner; private final boolean isInner;
private final NotNullLazyValue<Annotations> annotations; private final Annotations annotations;
private final NullableLazyValue<ClassDescriptorWithResolutionScopes> classObjectDescriptor; private final NullableLazyValue<ClassDescriptorWithResolutionScopes> classObjectDescriptor;
private final LazyClassMemberScope unsubstitutedMemberScope; private final LazyClassMemberScope unsubstitutedMemberScope;
@@ -88,7 +88,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
private final NullableLazyValue<Void> forceResolveAllContents; private final NullableLazyValue<Void> forceResolveAllContents;
public LazyClassDescriptor( public LazyClassDescriptor(
@NotNull ResolveSession resolveSession, @NotNull final ResolveSession resolveSession,
@NotNull DeclarationDescriptor containingDeclaration, @NotNull DeclarationDescriptor containingDeclaration,
@NotNull Name name, @NotNull Name name,
@NotNull JetClassLikeInfo classLikeInfo @NotNull JetClassLikeInfo classLikeInfo
@@ -124,12 +124,30 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
this.isInner = isInnerClass(modifierList); this.isInner = isInnerClass(modifierList);
StorageManager storageManager = resolveSession.getStorageManager(); StorageManager storageManager = resolveSession.getStorageManager();
this.annotations = storageManager.createLazyValue(new Function0<Annotations>() {
@Override
public Annotations invoke() { if (modifierList != null) {
return resolveAnnotations(); this.annotations = new LazyAnnotations(
} new LazyAnnotationsContext(
}); resolveSession.getAnnotationResolver(),
resolveSession.getStorageManager(),
resolveSession.getTrace()
) {
@NotNull
@Override
public JetScope getScope() {
JetClassLikeInfo ownerInfo = declarationProvider.getOwnerInfo();
return resolveSession.getScopeProvider().getResolutionScopeForDeclaration(ownerInfo.getScopeAnchor());
}
},
modifierList.getAnnotationEntries()
);
}
else {
this.annotations = Annotations.EMPTY;
}
this.classObjectDescriptor = storageManager.createNullableLazyValue(new Function0<ClassDescriptorWithResolutionScopes>() { this.classObjectDescriptor = storageManager.createNullableLazyValue(new Function0<ClassDescriptorWithResolutionScopes>() {
@Override @Override
public ClassDescriptorWithResolutionScopes invoke() { public ClassDescriptorWithResolutionScopes invoke() {
@@ -341,21 +359,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
@NotNull @NotNull
@Override @Override
public Annotations getAnnotations() { public Annotations getAnnotations() {
return annotations.invoke(); return annotations;
}
@NotNull
private Annotations resolveAnnotations() {
JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
JetModifierList modifierList = classInfo.getModifierList();
if (modifierList != null) {
AnnotationResolver annotationResolver = resolveSession.getAnnotationResolver();
JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(classInfo.getScopeAnchor());
return annotationResolver.resolveAnnotationsWithArguments(scopeForDeclaration, modifierList, resolveSession.getTrace());
}
else {
return Annotations.EMPTY;
}
} }
@Override @Override