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