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.isFinal(),
079 originalTypeConstructor.toString(),
080 typeParameters,
081 supertypes
082 );
083 }
084
085 return typeConstructor;
086 }
087
088 @NotNull
089 @Override
090 public JetScope getMemberScope(List<? extends 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 @NotNull
121 @Override
122 public List<AnnotationDescriptor> getAnnotations() {
123 return original.getAnnotations();
124 }
125
126 @NotNull
127 @Override
128 public Name getName() {
129 return original.getName();
130 }
131
132 @NotNull
133 @Override
134 public DeclarationDescriptor getOriginal() {
135 return original.getOriginal();
136 }
137
138 @NotNull
139 @Override
140 public DeclarationDescriptor getContainingDeclaration() {
141 return original.getContainingDeclaration();
142 }
143
144 @NotNull
145 @Override
146 public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
147 if (substitutor.isEmpty()) return this;
148 return new LazySubstitutingClassDescriptor(this, TypeSubstitutor.create(substitutor.getSubstitution(), getSubstitutor().getSubstitution()));
149 }
150
151 @Override
152 public JetType getClassObjectType() {
153 return original.getClassObjectType();
154 }
155
156 @Override
157 public ClassDescriptor getClassObjectDescriptor() {
158 return original.getClassObjectDescriptor();
159 }
160
161 @NotNull
162 @Override
163 public ClassKind getKind() {
164 return original.getKind();
165 }
166
167 @Override
168 @NotNull
169 public Modality getModality() {
170 return original.getModality();
171 }
172
173 @NotNull
174 @Override
175 public Visibility getVisibility() {
176 return original.getVisibility();
177 }
178
179 @Override
180 public boolean isInner() {
181 return original.isInner();
182 }
183
184 @Override
185 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
186 return visitor.visitClassDescriptor(this, data);
187 }
188
189 @Override
190 public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
191 throw new UnsupportedOperationException(); // TODO
192 }
193
194 @NotNull
195 @Override
196 public JetScope getUnsubstitutedInnerClassesScope() {
197 return original.getUnsubstitutedInnerClassesScope();
198 }
199
200 @Nullable
201 @Override
202 public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
203 return original.getUnsubstitutedPrimaryConstructor();
204 }
205 }