001    /*
002     * Copyright 2010-2016 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.types;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
021    import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
022    import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
023    import org.jetbrains.kotlin.resolve.scopes.MemberScope;
024    import org.jetbrains.kotlin.resolve.scopes.TypeIntersectionScope;
025    
026    import java.util.*;
027    
028    public class IntersectionTypeConstructor implements TypeConstructor {
029        private final Set<KotlinType> intersectedTypes;
030        private final int hashCode;
031    
032        public IntersectionTypeConstructor(Collection<KotlinType> typesToIntersect) {
033            assert !typesToIntersect.isEmpty() : "Attempt to create an empty intersection";
034    
035            this.intersectedTypes = new LinkedHashSet<KotlinType>(typesToIntersect);
036            this.hashCode = intersectedTypes.hashCode();
037        }
038    
039        @NotNull
040        @Override
041        public List<TypeParameterDescriptor> getParameters() {
042            return Collections.emptyList();
043        }
044    
045        @NotNull
046        @Override
047        public Collection<KotlinType> getSupertypes() {
048            return intersectedTypes;
049        }
050    
051        public MemberScope createScopeForKotlinType() {
052            return TypeIntersectionScope.create("member scope for intersection type " + this, intersectedTypes);
053        }
054    
055        @Override
056        public boolean isFinal() {
057            return false;
058        }
059    
060        @Override
061        public boolean isDenotable() {
062            return false;
063        }
064    
065        @Override
066        public ClassifierDescriptor getDeclarationDescriptor() {
067            return null;
068        }
069    
070        @NotNull
071        @Override
072        public KotlinBuiltIns getBuiltIns() {
073            return intersectedTypes.iterator().next().getConstructor().getBuiltIns();
074        }
075    
076        @Override
077        public String toString() {
078            return makeDebugNameForIntersectionType(intersectedTypes);
079        }
080    
081        private static String makeDebugNameForIntersectionType(Iterable<KotlinType> resultingTypes) {
082            StringBuilder debugName = new StringBuilder("{");
083            for (Iterator<KotlinType> iterator = resultingTypes.iterator(); iterator.hasNext(); ) {
084                KotlinType type = iterator.next();
085    
086                debugName.append(type.toString());
087                if (iterator.hasNext()) {
088                    debugName.append(" & ");
089                }
090            }
091            debugName.append("}");
092            return debugName.toString();
093        }
094    
095        @Override
096        public boolean equals(Object o) {
097            if (this == o) return true;
098            if (o == null || getClass() != o.getClass()) return false;
099    
100            IntersectionTypeConstructor that = (IntersectionTypeConstructor) o;
101    
102            if (intersectedTypes != null ? !intersectedTypes.equals(that.intersectedTypes) : that.intersectedTypes != null) return false;
103    
104            return true;
105        }
106    
107        @Override
108        public int hashCode() {
109            return hashCode;
110        }
111    }