001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.lang.descriptors.impl;
018
019 import kotlin.Function0;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.jet.lang.descriptors.*;
023 import org.jetbrains.jet.lang.resolve.name.Name;
024 import org.jetbrains.jet.lang.resolve.scopes.InnerClassesScopeWrapper;
025 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
026 import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
027 import org.jetbrains.jet.lang.types.*;
028 import org.jetbrains.jet.storage.NotNullLazyValue;
029 import org.jetbrains.jet.storage.StorageManager;
030
031 import java.util.List;
032 import java.util.Map;
033
034 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumClass;
035
036 public abstract class AbstractClassDescriptor implements ClassDescriptor {
037 private final Name name;
038 protected final NotNullLazyValue<JetType> defaultType;
039 private final NotNullLazyValue<JetScope> unsubstitutedInnerClassesScope;
040 private final NotNullLazyValue<ReceiverParameterDescriptor> thisAsReceiverParameter;
041
042 public AbstractClassDescriptor(@NotNull StorageManager storageManager, @NotNull Name name) {
043 this.name = name;
044 this.defaultType = storageManager.createLazyValue(new Function0<JetType>() {
045 @Override
046 public JetType invoke() {
047 return TypeUtils.makeUnsubstitutedType(AbstractClassDescriptor.this, getScopeForMemberLookup());
048 }
049 });
050 this.unsubstitutedInnerClassesScope = storageManager.createLazyValue(new Function0<JetScope>() {
051 @Override
052 public JetScope invoke() {
053 return new InnerClassesScopeWrapper(getScopeForMemberLookup());
054 }
055 });
056 this.thisAsReceiverParameter = storageManager.createLazyValue(new Function0<ReceiverParameterDescriptor>() {
057 @Override
058 public ReceiverParameterDescriptor invoke() {
059 return new LazyClassReceiverParameterDescriptor(AbstractClassDescriptor.this);
060 }
061 });
062 }
063
064 @NotNull
065 @Override
066 public Name getName() {
067 return name;
068 }
069
070 @NotNull
071 @Override
072 public DeclarationDescriptor getOriginal() {
073 return this;
074 }
075
076 @NotNull
077 protected abstract JetScope getScopeForMemberLookup();
078
079 @Nullable
080 @Override
081 public JetType getClassObjectType() {
082 if (getKind() == ClassKind.OBJECT) {
083 return getDefaultType();
084 }
085
086 if (getKind() == ClassKind.ENUM_ENTRY) {
087 DeclarationDescriptor enumClass = getContainingDeclaration();
088 assert isEnumClass(enumClass) : "Enum entry should be declared in enum class: " + this;
089 return ((ClassDescriptor) enumClass).getDefaultType();
090 }
091
092 ClassDescriptor classObject = getClassObjectDescriptor();
093 return classObject == null ? null : classObject.getDefaultType();
094 }
095
096 @NotNull
097 @Override
098 public JetScope getUnsubstitutedInnerClassesScope() {
099 return unsubstitutedInnerClassesScope.invoke();
100 }
101
102 @NotNull
103 @Override
104 public ReceiverParameterDescriptor getThisAsReceiverParameter() {
105 return thisAsReceiverParameter.invoke();
106 }
107
108 @NotNull
109 @Override
110 public JetScope getMemberScope(@NotNull List<? extends TypeProjection> typeArguments) {
111 assert typeArguments.size() == getTypeConstructor().getParameters().size() : "Illegal number of type arguments: expected "
112 + getTypeConstructor().getParameters().size() + " but was " + typeArguments.size()
113 + " for " + getTypeConstructor() + " " + getTypeConstructor().getParameters();
114 if (typeArguments.isEmpty()) return getScopeForMemberLookup();
115
116 List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
117 Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.buildSubstitutionContext(typeParameters, typeArguments);
118
119 TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext);
120 return new SubstitutingScope(getScopeForMemberLookup(), substitutor);
121 }
122
123 @NotNull
124 @Override
125 public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
126 if (substitutor.isEmpty()) {
127 return this;
128 }
129 return new LazySubstitutingClassDescriptor(this, substitutor);
130 }
131
132 @NotNull
133 @Override
134 public JetType getDefaultType() {
135 return defaultType.invoke();
136 }
137
138 @Override
139 public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
140 visitor.visitClassDescriptor(this, null);
141 }
142
143 @Override
144 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
145 return visitor.visitClassDescriptor(this, data);
146 }
147 }