001 package org.jetbrains.jet.lang.descriptors.impl;
002
003 import org.jetbrains.annotations.NotNull;
004 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
005 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
006 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorVisitor;
007 import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
008 import org.jetbrains.jet.lang.resolve.name.Name;
009 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
010 import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
011 import org.jetbrains.jet.lang.types.*;
012
013 import java.util.List;
014 import java.util.Map;
015
016 public abstract class AbstractClassDescriptor implements ClassDescriptor {
017 protected final Name name;
018 protected volatile JetType defaultType;
019
020 public AbstractClassDescriptor(@NotNull Name name) {
021 this.name = name;
022 }
023
024 @NotNull
025 @Override
026 public Name getName() {
027 return name;
028 }
029
030 @NotNull
031 @Override
032 public DeclarationDescriptor getOriginal() {
033 return this;
034 }
035
036 protected abstract JetScope getScopeForMemberLookup();
037
038 @NotNull
039 @Override
040 public JetScope getMemberScope(List<? extends TypeProjection> typeArguments) {
041 assert typeArguments.size() == getTypeConstructor().getParameters().size() : "Illegal number of type arguments: expected "
042 + getTypeConstructor().getParameters().size() + " but was " + typeArguments.size()
043 + " for " + getTypeConstructor() + " " + getTypeConstructor().getParameters();
044 if (typeArguments.isEmpty()) return getScopeForMemberLookup();
045
046 List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
047 Map<TypeConstructor, TypeProjection> substitutionContext = SubstitutionUtils.buildSubstitutionContext(typeParameters, typeArguments);
048
049 // Unsafe substitutor is OK, because no recursion can hurt us upon a trivial substitution:
050 // all the types are written explicitly in the code already, they can not get infinite.
051 // One exception is *-projections, but they need to be handled separately anyways.
052 TypeSubstitutor substitutor = TypeSubstitutor.createUnsafe(substitutionContext);
053 return new SubstitutingScope(getScopeForMemberLookup(), substitutor);
054 }
055
056 @NotNull
057 @Override
058 public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
059 if (substitutor.isEmpty()) {
060 return this;
061 }
062 return new LazySubstitutingClassDescriptor(this, substitutor);
063 }
064
065 @NotNull
066 @Override
067 public JetType getDefaultType() {
068 if (defaultType == null) {
069 defaultType = TypeUtils.makeUnsubstitutedType(this, getScopeForMemberLookup());
070 }
071 return defaultType;
072 }
073
074 @Override
075 public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
076 visitor.visitClassDescriptor(this, null);
077 }
078
079 @Override
080 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
081 return visitor.visitClassDescriptor(this, data);
082 }
083 }