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.types;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget;
022    import org.jetbrains.kotlin.renderer.DescriptorRenderer;
023    import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
024    
025    import java.util.Iterator;
026    import java.util.List;
027    
028    public abstract class AbstractKotlinType implements KotlinType {
029        @Nullable
030        @Override
031        public <T extends TypeCapability> T getCapability(@NotNull Class<T> capabilityClass) {
032            return getCapabilities().getCapability(capabilityClass);
033        }
034    
035        @NotNull
036        @Override
037        public TypeCapabilities getCapabilities() {
038            return TypeCapabilities.NONE.INSTANCE;
039        }
040    
041        @Override
042        public final int hashCode() {
043            int result = getConstructor().hashCode();
044            result = 31 * result + getArguments().hashCode();
045            result = 31 * result + (isMarkedNullable() ? 1 : 0);
046            return result;
047        }
048    
049        @Override
050        public final boolean equals(Object obj) {
051            if (this == obj) return true;
052            if (!(obj instanceof KotlinType)) return false;
053    
054            KotlinType type = (KotlinType) obj;
055    
056            return isMarkedNullable() == type.isMarkedNullable() && KotlinTypeChecker.FLEXIBLE_UNEQUAL_TO_INFLEXIBLE.equalTypes(this, type);
057        }
058    
059        @Override
060        public String toString() {
061            StringBuilder sb = new StringBuilder();
062    
063            for (AnnotationWithTarget annotationWithTarget : getAnnotations().getAllAnnotations()) {
064                sb.append("[");
065                sb.append(DescriptorRenderer.DEBUG_TEXT.renderAnnotation(
066                        annotationWithTarget.getAnnotation(), annotationWithTarget.getTarget()));
067                sb.append("] ");
068            }
069    
070            sb.append(getConstructor());
071    
072            List<TypeProjection> arguments = getArguments();
073            if (!arguments.isEmpty()) {
074                sb.append("<");
075                for (Iterator<TypeProjection> i = arguments.iterator(); i.hasNext(); ) {
076                    sb.append(i.next());
077                    if (i.hasNext()) {
078                        sb.append(", ");
079                    }
080                }
081                sb.append(">");
082            }
083    
084            if (isMarkedNullable()) {
085                sb.append("?");
086            }
087    
088            return sb.toString();
089        }
090    }