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 com.google.common.collect.Lists;
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.descriptors.annotations.AnnotationDescriptor;
024 import org.jetbrains.jet.lang.resolve.name.Name;
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
029 import java.util.Collection;
030 import java.util.List;
031
032 public class LazySubstitutingClassDescriptor implements ClassDescriptor {
033
034 private final ClassDescriptor original;
035 private final TypeSubstitutor originalSubstitutor;
036 private TypeSubstitutor newSubstitutor;
037 private List<TypeParameterDescriptor> typeParameters;
038 private TypeConstructor typeConstructor;
039 private JetType superclassType;
040
041 public LazySubstitutingClassDescriptor(ClassDescriptor descriptor, TypeSubstitutor substitutor) {
042 this.original = descriptor;
043 this.originalSubstitutor = substitutor;
044 }
045
046 private TypeSubstitutor getSubstitutor() {
047 if (newSubstitutor == null) {
048 if (originalSubstitutor.isEmpty()) {
049 newSubstitutor = originalSubstitutor;
050 }
051 else {
052 typeParameters = Lists.newArrayList();
053 newSubstitutor = DescriptorSubstitutor.substituteTypeParameters(original.getTypeConstructor().getParameters(), originalSubstitutor, this, typeParameters);
054 }
055 }
056 return newSubstitutor;
057 }
058
059 @NotNull
060 @Override
061 public TypeConstructor getTypeConstructor() {
062 TypeConstructor originalTypeConstructor = original.getTypeConstructor();
063 if (originalSubstitutor.isEmpty()) {
064 return originalTypeConstructor;
065 }
066
067 if (typeConstructor == null) {
068 TypeSubstitutor substitutor = getSubstitutor();
069
070 Collection<JetType> supertypes = Lists.newArrayList();
071 for (JetType supertype : originalTypeConstructor.getSupertypes()) {
072 supertypes.add(substitutor.substitute(supertype, Variance.INVARIANT));
073 }
074
075 typeConstructor = new TypeConstructorImpl(
076 this,
077 originalTypeConstructor.getAnnotations(),
078 originalTypeConstructor.isSealed(),
079 originalTypeConstructor.toString(),
080 typeParameters,
081 supertypes
082 );
083 }
084
085 return typeConstructor;
086 }
087
088 @NotNull
089 @Override
090 public JetScope getMemberScope(List<TypeProjection> typeArguments) {
091 JetScope memberScope = original.getMemberScope(typeArguments);
092 if (originalSubstitutor.isEmpty()) {
093 return memberScope;
094 }
095 return new SubstitutingScope(memberScope, getSubstitutor());
096 }
097
098 @NotNull
099 @Override
100 public JetType getDefaultType() {
101 throw new UnsupportedOperationException(); // TODO
102 }
103
104 @NotNull
105 @Override
106 public ReceiverParameterDescriptor getThisAsReceiverParameter() {
107 throw new UnsupportedOperationException(); // TODO
108 }
109
110 @NotNull
111 @Override
112 public Collection<ConstructorDescriptor> getConstructors() {
113 Collection<ConstructorDescriptor> r = Lists.newArrayList();
114 for (ConstructorDescriptor constructor : original.getConstructors()) {
115 r.add((ConstructorDescriptor) constructor.substitute(getSubstitutor()));
116 }
117 return r;
118 }
119
120 @Override
121 public List<AnnotationDescriptor> getAnnotations() {
122 return original.getAnnotations();
123 }
124
125 @NotNull
126 @Override
127 public Name getName() {
128 return original.getName();
129 }
130
131 @NotNull
132 @Override
133 public DeclarationDescriptor getOriginal() {
134 return original.getOriginal();
135 }
136
137 @NotNull
138 @Override
139 public DeclarationDescriptor getContainingDeclaration() {
140 return original.getContainingDeclaration();
141 }
142
143 @NotNull
144 @Override
145 public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
146 if (substitutor.isEmpty()) return this;
147 return new LazySubstitutingClassDescriptor(this, TypeSubstitutor.create(substitutor.getSubstitution(), getSubstitutor().getSubstitution()));
148 }
149
150 @Override
151 public JetType getClassObjectType() {
152 return original.getClassObjectType();
153 }
154
155 @Override
156 public ClassDescriptor getClassObjectDescriptor() {
157 return original.getClassObjectDescriptor();
158 }
159
160 @NotNull
161 @Override
162 public ClassKind getKind() {
163 return original.getKind();
164 }
165
166 @Override
167 @NotNull
168 public Modality getModality() {
169 return original.getModality();
170 }
171
172 @NotNull
173 @Override
174 public Visibility getVisibility() {
175 return original.getVisibility();
176 }
177
178 @Override
179 public boolean isInner() {
180 return original.isInner();
181 }
182
183 @Override
184 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
185 return visitor.visitClassDescriptor(this, data);
186 }
187
188 @Override
189 public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
190 throw new UnsupportedOperationException(); // TODO
191 }
192
193 @NotNull
194 @Override
195 public JetScope getUnsubstitutedInnerClassesScope() {
196 return original.getUnsubstitutedInnerClassesScope();
197 }
198
199 @Nullable
200 @Override
201 public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
202 return original.getUnsubstitutedPrimaryConstructor();
203 }
204 }