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.types;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
021    import org.jetbrains.jet.lang.descriptors.annotations.AnnotatedImpl;
022    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
023    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
024    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
025    
026    import java.util.Collections;
027    import java.util.Iterator;
028    import java.util.List;
029    
030    public final class JetTypeImpl extends AnnotatedImpl implements JetType {
031    
032        private final TypeConstructor constructor;
033        private final List<TypeProjection> arguments;
034        private final boolean nullable;
035        private final JetScope memberScope;
036    
037        public JetTypeImpl(List<AnnotationDescriptor> annotations, TypeConstructor constructor, boolean nullable, @NotNull List<TypeProjection> arguments, JetScope memberScope) {
038            super(annotations);
039    
040            if (memberScope instanceof ErrorUtils.ErrorScope) {
041                throw new IllegalStateException();
042            }
043    
044            this.constructor = constructor;
045            this.nullable = nullable;
046            this.arguments = arguments;
047            this.memberScope = memberScope;
048        }
049    
050        public JetTypeImpl(TypeConstructor constructor, JetScope memberScope) {
051            this(Collections.<AnnotationDescriptor>emptyList(), constructor, false, Collections.<TypeProjection>emptyList(), memberScope);
052        }
053    
054        public JetTypeImpl(@NotNull ClassDescriptor classDescriptor) {
055            this(Collections.<AnnotationDescriptor>emptyList(),
056                    classDescriptor.getTypeConstructor(),
057                    false,
058                    Collections.<TypeProjection>emptyList(),
059                    classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList()));
060        }
061    
062        @NotNull
063        @Override
064        public TypeConstructor getConstructor() {
065            return constructor;
066        }
067    
068        @NotNull
069        @Override
070        public List<TypeProjection> getArguments() {
071            return arguments;
072        }
073    
074        @Override
075        public boolean isNullable() {
076            return nullable;
077        }
078    
079        @NotNull
080        @Override
081        public JetScope getMemberScope() {
082            return memberScope;
083        }
084    
085        @Override
086        public String toString() {
087            return constructor + (arguments.isEmpty() ? "" : "<" + argumentsToString() + ">") + (isNullable() ? "?" : "");
088        }
089    
090        private StringBuilder argumentsToString() {
091            StringBuilder stringBuilder = new StringBuilder();
092            for (Iterator<TypeProjection> iterator = arguments.iterator(); iterator.hasNext();) {
093                TypeProjection argument = iterator.next();
094                stringBuilder.append(argument);
095                if (iterator.hasNext()) {
096                    stringBuilder.append(", ");
097                }
098            }
099            return stringBuilder;
100        }
101    
102        @Override
103        public boolean equals(Object o) {
104            if (this == o) return true;
105            if (!(o instanceof JetType)) return false;
106    
107            JetType type = (JetType) o;
108    
109            return nullable == type.isNullable() && JetTypeChecker.INSTANCE.equalTypes(this, type);
110        }
111    
112        @Override
113        public int hashCode() {
114            int result = constructor != null ? constructor.hashCode() : 0;
115            result = 31 * result + arguments.hashCode();
116            result = 31 * result + (nullable ? 1 : 0);
117            return result;
118        }
119    }