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;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
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.JetClassInfoUtil;
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 boolean isInner;
private ReceiverParameterDescriptor thisAsReceiverParameter;
private List<AnnotationDescriptor> annotations;
private ClassDescriptor classObjectDescriptor;
private boolean classObjectDescriptorResolved = false;
private final LazyValue<ReceiverParameterDescriptor> thisAsReceiverParameter;
private final LazyValue<List<AnnotationDescriptor>> annotations;
private final LazyValue<Optional<ClassDescriptor>> classObjectDescriptor;
private final LazyClassMemberScope unsubstitutedMemberScope;
private final JetScope unsubstitutedInnerClassesScope;
private JetScope scopeForClassHeaderResolution;
private JetScope scopeForMemberDeclarationResolution;
private JetScope scopeForPropertyInitializerResolution;
private final LazyValue<JetScope> scopeForClassHeaderResolution;
private final LazyValue<JetScope> scopeForMemberDeclarationResolution;
private final LazyValue<JetScope> scopeForPropertyInitializerResolution;
public LazyClassDescriptor(
@@ -111,6 +115,44 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
}
this.visibility = resolveVisibilityFromModifiers(modifierList, getDefaultClassVisibility(this));
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
@@ -126,59 +168,67 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
@NotNull
public JetScope getScopeForClassHeaderResolution() {
if (scopeForClassHeaderResolution == null) {
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;
return scopeForClassHeaderResolution.get();
}
@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() {
if (scopeForMemberDeclarationResolution == null) {
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;
return scopeForMemberDeclarationResolution.get();
}
@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() {
return scopeForPropertyInitializerResolution.get();
}
@NotNull
private JetScope computeScopeForPropertyInitializerResolution() {
ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor();
if (primaryConstructor == null) return getScopeForMemberDeclarationResolution();
if (scopeForPropertyInitializerResolution == null) {
WritableScopeImpl scope = new WritableScopeImpl(
JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Property Initializer Resolution");
WritableScopeImpl scope = new WritableScopeImpl(
JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Property Initializer Resolution");
List<ValueParameterDescriptor> parameters = primaryConstructor.getValueParameters();
for (ValueParameterDescriptor valueParameterDescriptor : parameters) {
scope.addVariableDescriptor(valueParameterDescriptor);
}
scope.changeLockLevel(WritableScope.LockLevel.READING);
scopeForPropertyInitializerResolution = new ChainedScope(
this,
"ScopeForPropertyInitializerResolution: " + getName(),
scope, getScopeForMemberDeclarationResolution());
List<ValueParameterDescriptor> parameters = primaryConstructor.getValueParameters();
for (ValueParameterDescriptor valueParameterDescriptor : parameters) {
scope.addVariableDescriptor(valueParameterDescriptor);
}
return scopeForPropertyInitializerResolution;
scope.changeLockLevel(WritableScope.LockLevel.READING);
return new ChainedScope(
this,
"ScopeForPropertyInitializerResolution: " + getName(),
scope, getScopeForMemberDeclarationResolution());
}
@NotNull
@@ -223,16 +273,18 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
@Override
public ClassDescriptor getClassObjectDescriptor() {
if (!classObjectDescriptorResolved) {
JetClassObject classObject = declarationProvider.getOwnerInfo().getClassObject();
return classObjectDescriptor.get().orNull();
}
JetClassLikeInfo classObjectInfo = getClassObjectInfo(classObject);
if (classObjectInfo != null) {
classObjectDescriptor = new LazyClassDescriptor(resolveSession, this, getClassObjectName(getName()), classObjectInfo);
}
classObjectDescriptorResolved = true;
@Nullable
private ClassDescriptor computeClassObjectDescriptor() {
JetClassObject classObject = declarationProvider.getOwnerInfo().getClassObject();
JetClassLikeInfo classObjectInfo = getClassObjectInfo(classObject);
if (classObjectInfo != null) {
return new LazyClassDescriptor(resolveSession, this, getClassObjectName(getName()), classObjectInfo);
}
return classObjectDescriptor;
return null;
}
@Nullable
@@ -281,27 +333,26 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
@NotNull
@Override
public ReceiverParameterDescriptor getThisAsReceiverParameter() {
if (thisAsReceiverParameter == null) {
thisAsReceiverParameter = DescriptorResolver.createLazyReceiverParameterDescriptor(this);
}
return thisAsReceiverParameter;
return thisAsReceiverParameter.get();
}
@Override
public List<AnnotationDescriptor> getAnnotations() {
if (annotations == null) {
JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
JetModifierList modifierList = classInfo.getModifierList();
if (modifierList != null) {
AnnotationResolver annotationResolver = resolveSession.getInjector().getAnnotationResolver();
JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(classInfo.getScopeAnchor());
annotations = annotationResolver.resolveAnnotations(scopeForDeclaration, modifierList, resolveSession.getTrace());
}
else {
annotations = Collections.emptyList();
}
return annotations.get();
}
@NotNull
private List<AnnotationDescriptor> resolveAnnotations() {
JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
JetModifierList modifierList = classInfo.getModifierList();
if (modifierList != null) {
AnnotationResolver annotationResolver = resolveSession.getInjector().getAnnotationResolver();
JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(classInfo.getScopeAnchor());
return annotationResolver.resolveAnnotations(scopeForDeclaration, modifierList, resolveSession.getTrace());
}
else {
return Collections.emptyList();
}
return annotations;
}
@NotNull
@@ -339,35 +390,16 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
}
private class LazyClassTypeConstructor implements LazyDescriptor, TypeConstructor {
private Collection<JetType> supertypes = null;
private List<TypeParameterDescriptor> parameters = null;
@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) {
private final LazyValue<Collection<JetType>> supertypes = resolveSession.getStorageManager().createLazyValue(new Computable<Collection<JetType>>() {
@Override
public Collection<JetType> compute() {
if (resolveSession.isClassSpecial(DescriptorUtils.getFQName(LazyClassDescriptor.this))) {
this.supertypes = Collections.emptyList();
return Collections.emptyList();
}
else {
JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
if (classOrObject == null) {
this.supertypes = Collections.emptyList();
return Collections.emptyList();
}
else {
List<JetType> allSupertypes = resolveSession.getInjector().getDescriptorResolver()
@@ -375,12 +407,38 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
LazyClassDescriptor.this, classOrObject,
resolveSession.getTrace());
List<JetType> validSupertypes = Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE));
this.supertypes = 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) {