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 kotlin.jvm.functions.Function1;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.kotlin.descriptors.*;
023    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
024    import org.jetbrains.kotlin.name.Name;
025    import org.jetbrains.kotlin.resolve.DescriptorUtils;
026    import org.jetbrains.kotlin.storage.LockBasedStorageManager;
027    import org.jetbrains.kotlin.types.KotlinType;
028    import org.jetbrains.kotlin.types.Variance;
029    
030    import java.util.ArrayList;
031    import java.util.List;
032    
033    import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getBuiltIns;
034    
035    public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor {
036        @Nullable
037        private final Function1<KotlinType, Void> reportCycleError;
038    
039        @NotNull
040        public static TypeParameterDescriptor createWithDefaultBound(
041                @NotNull DeclarationDescriptor containingDeclaration,
042                @NotNull Annotations annotations,
043                boolean reified,
044                @NotNull Variance variance,
045                @NotNull Name name,
046                int index
047        ) {
048            TypeParameterDescriptorImpl typeParameterDescriptor =
049                    createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index, SourceElement.NO_SOURCE);
050            typeParameterDescriptor.addUpperBound(getBuiltIns(containingDeclaration).getDefaultBound());
051            typeParameterDescriptor.setInitialized();
052            return typeParameterDescriptor;
053        }
054    
055        public static TypeParameterDescriptorImpl createForFurtherModification(
056                @NotNull DeclarationDescriptor containingDeclaration,
057                @NotNull Annotations annotations,
058                boolean reified,
059                @NotNull Variance variance,
060                @NotNull Name name,
061                int index,
062                @NotNull SourceElement source
063        ) {
064            return createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index, source,
065                                                /* reportSupertypeLoopError = */ null, SupertypeLoopChecker.EMPTY.INSTANCE);
066        }
067    
068        public static TypeParameterDescriptorImpl createForFurtherModification(
069                @NotNull DeclarationDescriptor containingDeclaration,
070                @NotNull Annotations annotations,
071                boolean reified,
072                @NotNull Variance variance,
073                @NotNull Name name,
074                int index,
075                @NotNull SourceElement source,
076                @Nullable Function1<KotlinType, Void> reportCycleError,
077                @NotNull SupertypeLoopChecker supertypeLoopsResolver
078        ) {
079            return new TypeParameterDescriptorImpl(containingDeclaration, annotations, reified, variance, name, index, source, reportCycleError,
080                                                   supertypeLoopsResolver);
081        }
082    
083        private final List<KotlinType> upperBounds = new ArrayList<KotlinType>(1);
084        private boolean initialized = false;
085    
086        private TypeParameterDescriptorImpl(
087                @NotNull DeclarationDescriptor containingDeclaration,
088                @NotNull Annotations annotations,
089                boolean reified,
090                @NotNull Variance variance,
091                @NotNull Name name,
092                int index,
093                @NotNull SourceElement source,
094                @Nullable Function1<KotlinType, Void> reportCycleError,
095                @NotNull SupertypeLoopChecker supertypeLoopsChecker
096        ) {
097            super(LockBasedStorageManager.NO_LOCKS, containingDeclaration, annotations, name, variance, reified, index, source,
098                  supertypeLoopsChecker);
099            this.reportCycleError = reportCycleError;
100        }
101    
102        private void checkInitialized() {
103            if (!initialized) {
104                throw new IllegalStateException("Type parameter descriptor is not initialized: " + nameForAssertions());
105            }
106        }
107    
108        private void checkUninitialized() {
109            if (initialized) {
110                throw new IllegalStateException("Type parameter descriptor is already initialized: " + nameForAssertions());
111            }
112        }
113    
114        private String nameForAssertions() {
115            return getName() + " declared in " + DescriptorUtils.getFqName(getContainingDeclaration());
116        }
117    
118        public void setInitialized() {
119            checkUninitialized();
120            initialized = true;
121        }
122    
123        public void addUpperBound(@NotNull KotlinType bound) {
124            checkUninitialized();
125            doAddUpperBound(bound);
126        }
127    
128        private void doAddUpperBound(KotlinType bound) {
129            if (bound.isError()) return;
130            upperBounds.add(bound); // TODO : Duplicates?
131        }
132    
133        public void addDefaultUpperBound() {
134            checkUninitialized();
135    
136            if (upperBounds.isEmpty()) {
137                doAddUpperBound(getBuiltIns(getContainingDeclaration()).getDefaultBound());
138            }
139        }
140    
141        @Override
142        protected void reportSupertypeLoopError(@NotNull KotlinType type) {
143            if (reportCycleError == null) return;
144            reportCycleError.invoke(type);
145        }
146    
147        @NotNull
148        @Override
149        protected List<KotlinType> resolveUpperBounds() {
150            checkInitialized();
151            return upperBounds;
152        }
153    }