001    /*
002     * Copyright 2010-2015 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.kotlin.descriptors.impl;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.kotlin.descriptors.*;
022    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
023    import org.jetbrains.kotlin.name.Name;
024    import org.jetbrains.kotlin.resolve.scopes.JetScope;
025    import org.jetbrains.kotlin.resolve.scopes.SubstitutingScope;
026    import org.jetbrains.kotlin.types.*;
027    
028    import java.util.ArrayList;
029    import java.util.Collection;
030    import java.util.List;
031    
032    public class LazySubstitutingClassDescriptor implements ClassDescriptor {
033        private final ClassDescriptor original;
034        private final TypeSubstitutor originalSubstitutor;
035        private TypeSubstitutor newSubstitutor;
036        private List<TypeParameterDescriptor> typeParameters;
037        private TypeConstructor typeConstructor;
038    
039        public LazySubstitutingClassDescriptor(ClassDescriptor descriptor, TypeSubstitutor substitutor) {
040            this.original = descriptor;
041            this.originalSubstitutor = substitutor;
042        }
043    
044        private TypeSubstitutor getSubstitutor() {
045            if (newSubstitutor == null) {
046                if (originalSubstitutor.isEmpty()) {
047                    newSubstitutor = originalSubstitutor;
048                }
049                else {
050                    List<TypeParameterDescriptor> originalTypeParameters = original.getTypeConstructor().getParameters();
051                    typeParameters = new ArrayList<TypeParameterDescriptor>(originalTypeParameters.size());
052                    newSubstitutor = DescriptorSubstitutor.substituteTypeParameters(
053                            originalTypeParameters, originalSubstitutor.getSubstitution(), this, typeParameters
054                    );
055                }
056            }
057            return newSubstitutor;
058        }
059    
060        @NotNull
061        @Override
062        public TypeConstructor getTypeConstructor() {
063            TypeConstructor originalTypeConstructor = original.getTypeConstructor();
064            if (originalSubstitutor.isEmpty()) {
065                return originalTypeConstructor;
066            }
067    
068            if (typeConstructor == null) {
069                TypeSubstitutor substitutor = getSubstitutor();
070    
071                Collection<JetType> originalSupertypes = originalTypeConstructor.getSupertypes();
072                Collection<JetType> supertypes = new ArrayList<JetType>(originalSupertypes.size());
073                for (JetType supertype : originalSupertypes) {
074                    supertypes.add(substitutor.substitute(supertype, Variance.INVARIANT));
075                }
076    
077                typeConstructor = TypeConstructorImpl.createForClass(
078                        this,
079                        originalTypeConstructor.getAnnotations(),
080                        originalTypeConstructor.isFinal(),
081                        originalTypeConstructor.toString(),
082                        typeParameters,
083                        supertypes
084                );
085            }
086    
087            return typeConstructor;
088        }
089    
090        @NotNull
091        @Override
092        public JetScope getMemberScope(@NotNull List<? extends TypeProjection> typeArguments) {
093            JetScope memberScope = original.getMemberScope(typeArguments);
094            if (originalSubstitutor.isEmpty()) {
095                return memberScope;
096            }
097            return new SubstitutingScope(memberScope, getSubstitutor());
098        }
099    
100        @NotNull
101        @Override
102        public JetScope getMemberScope(@NotNull TypeSubstitution typeSubstitution) {
103            JetScope memberScope = original.getMemberScope(typeSubstitution);
104            if (originalSubstitutor.isEmpty()) {
105                return memberScope;
106            }
107            return new SubstitutingScope(memberScope, getSubstitutor());
108        }
109    
110        @NotNull
111        @Override
112        public JetScope getUnsubstitutedMemberScope() {
113            JetScope memberScope = original.getUnsubstitutedMemberScope();
114            if (originalSubstitutor.isEmpty()) {
115                return memberScope;
116            }
117            return new SubstitutingScope(memberScope, getSubstitutor());
118        }
119    
120        @NotNull
121        @Override
122        public JetScope getStaticScope() {
123            return original.getStaticScope();
124        }
125    
126        @NotNull
127        @Override
128        public JetType getDefaultType() {
129            List<TypeProjection> typeProjections = TypeUtils.getDefaultTypeProjections(getTypeConstructor().getParameters());
130            return JetTypeImpl.create(
131                    getAnnotations(),
132                    this,
133                    false,
134                    typeProjections
135            );
136        }
137    
138        @NotNull
139        @Override
140        public ReceiverParameterDescriptor getThisAsReceiverParameter() {
141            throw new UnsupportedOperationException(); // TODO
142        }
143    
144        @NotNull
145        @Override
146        public Collection<ConstructorDescriptor> getConstructors() {
147            Collection<ConstructorDescriptor> originalConstructors = original.getConstructors();
148            Collection<ConstructorDescriptor> result = new ArrayList<ConstructorDescriptor>(originalConstructors.size());
149            for (ConstructorDescriptor constructor : originalConstructors) {
150                result.add((ConstructorDescriptor) constructor.substitute(getSubstitutor()));
151            }
152            return result;
153        }
154    
155        @NotNull
156        @Override
157        public Annotations getAnnotations() {
158            return original.getAnnotations();
159        }
160    
161        @NotNull
162        @Override
163        public Name getName() {
164            return original.getName();
165        }
166    
167        @NotNull
168        @Override
169        public DeclarationDescriptorWithSource getOriginal() {
170            return original.getOriginal();
171        }
172    
173        @NotNull
174        @Override
175        public DeclarationDescriptor getContainingDeclaration() {
176            return original.getContainingDeclaration();
177        }
178    
179        @NotNull
180        @Override
181        public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
182            if (substitutor.isEmpty()) return this;
183            return new LazySubstitutingClassDescriptor(this, TypeSubstitutor.createChainedSubstitutor(substitutor.getSubstitution(), getSubstitutor().getSubstitution()));
184        }
185    
186        @Override
187        public ClassDescriptor getCompanionObjectDescriptor() {
188            return original.getCompanionObjectDescriptor();
189        }
190    
191        @NotNull
192        @Override
193        public ClassKind getKind() {
194            return original.getKind();
195        }
196    
197        @Override
198        @NotNull
199        public Modality getModality() {
200            return original.getModality();
201        }
202    
203        @NotNull
204        @Override
205        public Visibility getVisibility() {
206            return original.getVisibility();
207        }
208    
209        @Override
210        public boolean isInner() {
211            return original.isInner();
212        }
213    
214        @Override
215        public boolean isCompanionObject() {
216            return original.isCompanionObject();
217        }
218    
219        @Override
220        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
221            return visitor.visitClassDescriptor(this, data);
222        }
223    
224        @Override
225        public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
226            throw new UnsupportedOperationException(); // TODO
227        }
228    
229        @NotNull
230        @Override
231        public JetScope getUnsubstitutedInnerClassesScope() {
232            return original.getUnsubstitutedInnerClassesScope();
233        }
234    
235        @Nullable
236        @Override
237        public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
238            return original.getUnsubstitutedPrimaryConstructor();
239        }
240    
241        @NotNull
242        @Override
243        public SourceElement getSource() {
244            return SourceElement.NO_SOURCE;
245        }
246    }