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 }