Thread-safe lazy values introduced into LazyClassDescriptor

This commit is contained in:
Andrey Breslav
2013-02-08 13:22:22 +04:00
parent 59b78e3628
commit 8a240e82bd
@@ -16,17 +16,22 @@
package org.jetbrains.jet.lang.resolve.lazy; package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.base.Optional;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.AnnotationResolver;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.lazy.data.FilteringClassLikeInfo; import org.jetbrains.jet.lang.resolve.lazy.data.FilteringClassLikeInfo;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil; import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo; import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
@@ -64,17 +69,16 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
private final ClassKind kind; private final ClassKind kind;
private final boolean isInner; private final boolean isInner;
private ReceiverParameterDescriptor thisAsReceiverParameter; private final LazyValue<ReceiverParameterDescriptor> thisAsReceiverParameter;
private List<AnnotationDescriptor> annotations; private final LazyValue<List<AnnotationDescriptor>> annotations;
private ClassDescriptor classObjectDescriptor; private final LazyValue<Optional<ClassDescriptor>> classObjectDescriptor;
private boolean classObjectDescriptorResolved = false;
private final LazyClassMemberScope unsubstitutedMemberScope; private final LazyClassMemberScope unsubstitutedMemberScope;
private final JetScope unsubstitutedInnerClassesScope; private final JetScope unsubstitutedInnerClassesScope;
private JetScope scopeForClassHeaderResolution; private final LazyValue<JetScope> scopeForClassHeaderResolution;
private JetScope scopeForMemberDeclarationResolution; private final LazyValue<JetScope> scopeForMemberDeclarationResolution;
private JetScope scopeForPropertyInitializerResolution; private final LazyValue<JetScope> scopeForPropertyInitializerResolution;
public LazyClassDescriptor( public LazyClassDescriptor(
@@ -111,6 +115,44 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
} }
this.visibility = resolveVisibilityFromModifiers(modifierList, getDefaultClassVisibility(this)); this.visibility = resolveVisibilityFromModifiers(modifierList, getDefaultClassVisibility(this));
this.isInner = isInnerClass(modifierList); this.isInner = isInnerClass(modifierList);
StorageManager storageManager = resolveSession.getStorageManager();
this.thisAsReceiverParameter = storageManager.createLazyValue(new Computable<ReceiverParameterDescriptor>() {
@Override
public ReceiverParameterDescriptor compute() {
return DescriptorResolver.createLazyReceiverParameterDescriptor(LazyClassDescriptor.this);
}
});
this.annotations = storageManager.createLazyValue(new Computable<List<AnnotationDescriptor>>() {
@Override
public List<AnnotationDescriptor> compute() {
return resolveAnnotations();
}
});
this.classObjectDescriptor = storageManager.createLazyValue(new Computable<Optional<ClassDescriptor>>() {
@Override
public Optional<ClassDescriptor> compute() {
return Optional.fromNullable(computeClassObjectDescriptor());
}
});
this.scopeForClassHeaderResolution = storageManager.createLazyValue(new Computable<JetScope>() {
@Override
public JetScope compute() {
return computeScopeForClassHeaderResolution();
}
});
this.scopeForMemberDeclarationResolution = storageManager.createLazyValue(new Computable<JetScope>() {
@Override
public JetScope compute() {
return computeScopeForMemberDeclarationResolution();
}
});
this.scopeForPropertyInitializerResolution = storageManager.createLazyValue(new Computable<JetScope>() {
@Override
public JetScope compute() {
return computeScopeForPropertyInitializerResolution();
}
});
} }
@Override @Override
@@ -126,59 +168,67 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
@NotNull @NotNull
public JetScope getScopeForClassHeaderResolution() { public JetScope getScopeForClassHeaderResolution() {
if (scopeForClassHeaderResolution == null) { return scopeForClassHeaderResolution.get();
WritableScopeImpl scope = new WritableScopeImpl(
JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Class Header Resolution");
for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) {
scope.addClassifierDescriptor(typeParameterDescriptor);
}
scope.changeLockLevel(WritableScope.LockLevel.READING);
PsiElement scopeAnchor = declarationProvider.getOwnerInfo().getScopeAnchor();
scopeForClassHeaderResolution = new ChainedScope(
this,
"ScopeForClassHeaderResolution: " + getName(),
scope, getScopeProvider().getResolutionScopeForDeclaration(scopeAnchor));
}
return scopeForClassHeaderResolution;
} }
@NotNull
private JetScope computeScopeForClassHeaderResolution() {
WritableScopeImpl scope = new WritableScopeImpl(
JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Class Header Resolution");
for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) {
scope.addClassifierDescriptor(typeParameterDescriptor);
}
scope.changeLockLevel(WritableScope.LockLevel.READING);
PsiElement scopeAnchor = declarationProvider.getOwnerInfo().getScopeAnchor();
return new ChainedScope(
this,
"ScopeForClassHeaderResolution: " + getName(),
scope, getScopeProvider().getResolutionScopeForDeclaration(scopeAnchor));
}
@NotNull
public JetScope getScopeForMemberDeclarationResolution() { public JetScope getScopeForMemberDeclarationResolution() {
if (scopeForMemberDeclarationResolution == null) { return scopeForMemberDeclarationResolution.get();
WritableScopeImpl scope = new WritableScopeImpl(
JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Member Declaration Resolution");
scope.addLabeledDeclaration(this);
scope.changeLockLevel(WritableScope.LockLevel.READING);
scopeForMemberDeclarationResolution = new ChainedScope(
this,
"ScopeForMemberDeclarationResolution: " + getName(),
scope, getScopeForMemberLookup(), getScopeForClassHeaderResolution());
}
return scopeForMemberDeclarationResolution;
} }
@NotNull
private JetScope computeScopeForMemberDeclarationResolution() {
WritableScopeImpl scope = new WritableScopeImpl(
JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Member Declaration Resolution");
scope.addLabeledDeclaration(this);
scope.changeLockLevel(WritableScope.LockLevel.READING);
return new ChainedScope(
this,
"ScopeForMemberDeclarationResolution: " + getName(),
scope, getScopeForMemberLookup(), getScopeForClassHeaderResolution());
}
@NotNull
public JetScope getScopeForPropertyInitializerResolution() { public JetScope getScopeForPropertyInitializerResolution() {
return scopeForPropertyInitializerResolution.get();
}
@NotNull
private JetScope computeScopeForPropertyInitializerResolution() {
ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor(); ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor();
if (primaryConstructor == null) return getScopeForMemberDeclarationResolution(); if (primaryConstructor == null) return getScopeForMemberDeclarationResolution();
if (scopeForPropertyInitializerResolution == null) { WritableScopeImpl scope = new WritableScopeImpl(
WritableScopeImpl scope = new WritableScopeImpl( JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Property Initializer Resolution");
JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Property Initializer Resolution");
List<ValueParameterDescriptor> parameters = primaryConstructor.getValueParameters(); List<ValueParameterDescriptor> parameters = primaryConstructor.getValueParameters();
for (ValueParameterDescriptor valueParameterDescriptor : parameters) { for (ValueParameterDescriptor valueParameterDescriptor : parameters) {
scope.addVariableDescriptor(valueParameterDescriptor); scope.addVariableDescriptor(valueParameterDescriptor);
}
scope.changeLockLevel(WritableScope.LockLevel.READING);
scopeForPropertyInitializerResolution = new ChainedScope(
this,
"ScopeForPropertyInitializerResolution: " + getName(),
scope, getScopeForMemberDeclarationResolution());
} }
return scopeForPropertyInitializerResolution;
scope.changeLockLevel(WritableScope.LockLevel.READING);
return new ChainedScope(
this,
"ScopeForPropertyInitializerResolution: " + getName(),
scope, getScopeForMemberDeclarationResolution());
} }
@NotNull @NotNull
@@ -223,16 +273,18 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
@Override @Override
public ClassDescriptor getClassObjectDescriptor() { public ClassDescriptor getClassObjectDescriptor() {
if (!classObjectDescriptorResolved) { return classObjectDescriptor.get().orNull();
JetClassObject classObject = declarationProvider.getOwnerInfo().getClassObject(); }
JetClassLikeInfo classObjectInfo = getClassObjectInfo(classObject); @Nullable
if (classObjectInfo != null) { private ClassDescriptor computeClassObjectDescriptor() {
classObjectDescriptor = new LazyClassDescriptor(resolveSession, this, getClassObjectName(getName()), classObjectInfo); JetClassObject classObject = declarationProvider.getOwnerInfo().getClassObject();
}
classObjectDescriptorResolved = true; JetClassLikeInfo classObjectInfo = getClassObjectInfo(classObject);
if (classObjectInfo != null) {
return new LazyClassDescriptor(resolveSession, this, getClassObjectName(getName()), classObjectInfo);
} }
return classObjectDescriptor; return null;
} }
@Nullable @Nullable
@@ -281,27 +333,26 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
@NotNull @NotNull
@Override @Override
public ReceiverParameterDescriptor getThisAsReceiverParameter() { public ReceiverParameterDescriptor getThisAsReceiverParameter() {
if (thisAsReceiverParameter == null) { return thisAsReceiverParameter.get();
thisAsReceiverParameter = DescriptorResolver.createLazyReceiverParameterDescriptor(this);
}
return thisAsReceiverParameter;
} }
@Override @Override
public List<AnnotationDescriptor> getAnnotations() { public List<AnnotationDescriptor> getAnnotations() {
if (annotations == null) { return annotations.get();
JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo(); }
JetModifierList modifierList = classInfo.getModifierList();
if (modifierList != null) { @NotNull
AnnotationResolver annotationResolver = resolveSession.getInjector().getAnnotationResolver(); private List<AnnotationDescriptor> resolveAnnotations() {
JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(classInfo.getScopeAnchor()); JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
annotations = annotationResolver.resolveAnnotations(scopeForDeclaration, modifierList, resolveSession.getTrace()); JetModifierList modifierList = classInfo.getModifierList();
} if (modifierList != null) {
else { AnnotationResolver annotationResolver = resolveSession.getInjector().getAnnotationResolver();
annotations = Collections.emptyList(); JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(classInfo.getScopeAnchor());
} return annotationResolver.resolveAnnotations(scopeForDeclaration, modifierList, resolveSession.getTrace());
}
else {
return Collections.emptyList();
} }
return annotations;
} }
@NotNull @NotNull
@@ -339,35 +390,16 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
} }
private class LazyClassTypeConstructor implements LazyDescriptor, TypeConstructor { private class LazyClassTypeConstructor implements LazyDescriptor, TypeConstructor {
private Collection<JetType> supertypes = null; private final LazyValue<Collection<JetType>> supertypes = resolveSession.getStorageManager().createLazyValue(new Computable<Collection<JetType>>() {
private List<TypeParameterDescriptor> parameters = null; @Override
public Collection<JetType> compute() {
@NotNull
@Override
public List<TypeParameterDescriptor> getParameters() {
if (parameters == null) {
JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
List<JetTypeParameter> typeParameters = classInfo.getTypeParameters();
parameters = new ArrayList<TypeParameterDescriptor>(typeParameters.size());
for (int i = 0; i < typeParameters.size(); i++) {
parameters.add(new LazyTypeParameterDescriptor(resolveSession, LazyClassDescriptor.this, typeParameters.get(i), i));
}
}
return parameters;
}
@NotNull
@Override
public Collection<JetType> getSupertypes() {
if (supertypes == null) {
if (resolveSession.isClassSpecial(DescriptorUtils.getFQName(LazyClassDescriptor.this))) { if (resolveSession.isClassSpecial(DescriptorUtils.getFQName(LazyClassDescriptor.this))) {
this.supertypes = Collections.emptyList(); return Collections.emptyList();
} }
else { else {
JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject(); JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
if (classOrObject == null) { if (classOrObject == null) {
this.supertypes = Collections.emptyList(); return Collections.emptyList();
} }
else { else {
List<JetType> allSupertypes = resolveSession.getInjector().getDescriptorResolver() List<JetType> allSupertypes = resolveSession.getInjector().getDescriptorResolver()
@@ -375,12 +407,38 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
LazyClassDescriptor.this, classOrObject, LazyClassDescriptor.this, classOrObject,
resolveSession.getTrace()); resolveSession.getTrace());
List<JetType> validSupertypes = Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE)); List<JetType> validSupertypes = Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE));
this.supertypes = validSupertypes;
findAndDisconnectLoopsInTypeHierarchy(validSupertypes); findAndDisconnectLoopsInTypeHierarchy(validSupertypes);
return validSupertypes;
} }
} }
} }
return supertypes; });
private final LazyValue<List<TypeParameterDescriptor>> parameters = resolveSession.getStorageManager().createLazyValue(new Computable<List<TypeParameterDescriptor>>() {
@Override
public List<TypeParameterDescriptor> compute() {
JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
List<JetTypeParameter> typeParameters = classInfo.getTypeParameters();
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>(typeParameters.size());
for (int i = 0; i < typeParameters.size(); i++) {
parameters.add(new LazyTypeParameterDescriptor(resolveSession, LazyClassDescriptor.this, typeParameters.get(i), i));
}
return parameters;
}
});
@NotNull
@Override
public List<TypeParameterDescriptor> getParameters() {
return parameters.get();
}
@NotNull
@Override
public Collection<JetType> getSupertypes() {
return supertypes.get();
} }
private void findAndDisconnectLoopsInTypeHierarchy(List<JetType> supertypes) { private void findAndDisconnectLoopsInTypeHierarchy(List<JetType> supertypes) {