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.resolve;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.kotlin.descriptors.CallableDescriptor;
021    import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
022    import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
023    import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor;
024    import org.jetbrains.kotlin.types.JetType;
025    import org.jetbrains.kotlin.types.TypesPackage;
026    import org.jetbrains.kotlin.types.checker.JetTypeChecker;
027    
028    import java.util.List;
029    
030    import static org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.INCOMPATIBLE;
031    
032    public class OverloadUtil {
033    
034        /**
035         * Does not check names.
036         */
037        public static OverloadCompatibilityInfo isOverloadable(CallableDescriptor a, CallableDescriptor b) {
038            int abc = braceCount(a);
039            int bbc = braceCount(b);
040            
041            if (abc != bbc) {
042                return OverloadCompatibilityInfo.success();
043            }
044            
045            OverridingUtil.OverrideCompatibilityInfo overrideCompatibilityInfo = isOverloadableBy(a, b);
046            switch (overrideCompatibilityInfo.getResult()) {
047                case OVERRIDABLE:
048                case CONFLICT:
049                    return OverloadCompatibilityInfo.someError();
050                case INCOMPATIBLE:
051                    return OverloadCompatibilityInfo.success();
052                default:
053                    throw new IllegalStateException();
054            }
055        }
056    
057        @NotNull
058        private static OverridingUtil.OverrideCompatibilityInfo isOverloadableBy(
059                @NotNull CallableDescriptor superDescriptor,
060                @NotNull CallableDescriptor subDescriptor
061        ) {
062            OverridingUtil.OverrideCompatibilityInfo
063                    receiverAndParameterResult = OverridingUtil.checkReceiverAndParameterCount(superDescriptor, subDescriptor);
064            if (receiverAndParameterResult != null) {
065                return receiverAndParameterResult;
066            }
067    
068            List<JetType> superValueParameters = OverridingUtil.compiledValueParameters(superDescriptor);
069            List<JetType> subValueParameters = OverridingUtil.compiledValueParameters(subDescriptor);
070    
071            for (int i = 0; i < superValueParameters.size(); ++i) {
072                JetType superValueParameterType = OverridingUtil.getUpperBound(superValueParameters.get(i));
073                JetType subValueParameterType = OverridingUtil.getUpperBound(subValueParameters.get(i));
074                if (!JetTypeChecker.DEFAULT.equalTypes(superValueParameterType, subValueParameterType)
075                    || TypesPackage.oneMoreSpecificThanAnother(subValueParameterType, superValueParameterType)) {
076                    return OverridingUtil.OverrideCompatibilityInfo
077                            .valueParameterTypeMismatch(superValueParameterType, subValueParameterType, INCOMPATIBLE);
078                }
079            }
080    
081            return OverridingUtil.OverrideCompatibilityInfo.success();
082        }
083    
084        private static int braceCount(CallableDescriptor a) {
085            if (a instanceof PropertyDescriptor) {
086                return 0;
087            }
088            else if (a instanceof SimpleFunctionDescriptor) {
089                return 1;
090            }
091            else if (a instanceof ConstructorDescriptor) {
092                return 1;
093            }
094            else {
095                throw new IllegalStateException();
096            }
097        }
098    
099        public static class OverloadCompatibilityInfo {
100    
101            private static final OverloadCompatibilityInfo SUCCESS = new OverloadCompatibilityInfo(true, "SUCCESS");
102            
103            public static OverloadCompatibilityInfo success() {
104                return SUCCESS;
105            }
106            
107            public static OverloadCompatibilityInfo someError() {
108                return new OverloadCompatibilityInfo(false, "XXX");
109            }
110            
111    
112            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
113    
114            private final boolean isSuccess;
115            private final String message;
116    
117            public OverloadCompatibilityInfo(boolean success, String message) {
118                isSuccess = success;
119                this.message = message;
120            }
121    
122            public boolean isSuccess() {
123                return isSuccess;
124            }
125    
126            public String getMessage() {
127                return message;
128            }
129    
130        }
131    
132    }