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 }