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.KotlinType; 025 import org.jetbrains.kotlin.types.TypeCapabilitiesKt; 026 import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; 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<KotlinType> superValueParameters = OverridingUtil.compiledValueParameters(superDescriptor); 069 List<KotlinType> subValueParameters = OverridingUtil.compiledValueParameters(subDescriptor); 070 071 for (int i = 0; i < superValueParameters.size(); ++i) { 072 KotlinType superValueParameterType = OverridingUtil.getUpperBound(superValueParameters.get(i)); 073 KotlinType subValueParameterType = OverridingUtil.getUpperBound(subValueParameters.get(i)); 074 if (!KotlinTypeChecker.DEFAULT.equalTypes(superValueParameterType, subValueParameterType) 075 || TypeCapabilitiesKt.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 }