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.calls; 018 019 import com.google.common.collect.Lists; 020 import org.jetbrains.annotations.NotNull; 021 import org.jetbrains.kotlin.builtins.KotlinBuiltIns; 022 import org.jetbrains.kotlin.descriptors.CallableDescriptor; 023 import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; 024 import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor; 025 import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; 026 import org.jetbrains.kotlin.psi.Call; 027 import org.jetbrains.kotlin.psi.JetExpression; 028 import org.jetbrains.kotlin.psi.JetSimpleNameExpression; 029 import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem; 030 import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver; 031 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; 032 import org.jetbrains.kotlin.types.*; 033 034 import java.util.Collections; 035 import java.util.List; 036 037 import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION; 038 import static org.jetbrains.kotlin.types.TypeUtils.DONT_CARE; 039 040 public class CallResolverUtil { 041 public static enum ResolveArgumentsMode { 042 RESOLVE_FUNCTION_ARGUMENTS, 043 SHAPE_FUNCTION_ARGUMENTS 044 } 045 046 private CallResolverUtil() {} 047 048 049 public static boolean hasUnknownFunctionParameter(@NotNull JetType type) { 050 assert KotlinBuiltIns.isFunctionOrExtensionFunctionType(type); 051 List<TypeProjection> arguments = type.getArguments(); 052 // last argument is return type of function type 053 List<TypeProjection> functionParameters = arguments.subList(0, arguments.size() - 1); 054 for (TypeProjection functionParameter : functionParameters) { 055 if (TypeUtils.containsSpecialType(functionParameter.getType(), DONT_CARE) 056 || ErrorUtils.containsUninferredParameter(functionParameter.getType())) { 057 return true; 058 } 059 } 060 return false; 061 } 062 063 public static boolean hasUnknownReturnType(@NotNull JetType type) { 064 assert KotlinBuiltIns.isFunctionOrExtensionFunctionType(type); 065 JetType returnTypeFromFunctionType = KotlinBuiltIns.getReturnTypeFromFunctionType(type); 066 return ErrorUtils.containsErrorType(returnTypeFromFunctionType); 067 } 068 069 public static JetType replaceReturnTypeByUnknown(@NotNull JetType type) { 070 assert KotlinBuiltIns.isFunctionOrExtensionFunctionType(type); 071 List<TypeProjection> arguments = type.getArguments(); 072 List<TypeProjection> newArguments = Lists.newArrayList(); 073 newArguments.addAll(arguments.subList(0, arguments.size() - 1)); 074 newArguments.add(new TypeProjectionImpl(Variance.INVARIANT, DONT_CARE)); 075 return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isMarkedNullable(), newArguments, type.getMemberScope()); 076 } 077 078 private static boolean hasReturnTypeDependentOnUninferredParams( 079 @NotNull CallableDescriptor candidateDescriptor, 080 @NotNull ConstraintSystem constraintSystem 081 ) { 082 JetType returnType = candidateDescriptor.getReturnType(); 083 if (returnType == null) return false; 084 085 for (TypeParameterDescriptor typeVariable : constraintSystem.getTypeVariables()) { 086 JetType inferredValueForTypeVariable = constraintSystem.getTypeBounds(typeVariable).getValue(); 087 if (inferredValueForTypeVariable == null) { 088 if (TypeUtils.dependsOnTypeParameters(returnType, Collections.singleton(typeVariable))) { 089 return true; 090 } 091 } 092 } 093 return false; 094 } 095 096 public static boolean hasInferredReturnType( 097 @NotNull CallableDescriptor candidateDescriptor, 098 @NotNull ConstraintSystem constraintSystem 099 ) { 100 if (hasReturnTypeDependentOnUninferredParams(candidateDescriptor, constraintSystem)) return false; 101 102 // Expected type mismatch was reported before as 'TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH' 103 if (constraintSystem.getStatus().hasOnlyErrorsFromPosition(EXPECTED_TYPE_POSITION.position())) return false; 104 return true; 105 } 106 107 @NotNull 108 public static JetType getErasedReceiverType( 109 @NotNull ReceiverParameterDescriptor receiverParameterDescriptor, 110 @NotNull CallableDescriptor descriptor 111 ) { 112 JetType receiverType = receiverParameterDescriptor.getType(); 113 for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) { 114 if (typeParameter.getTypeConstructor().equals(receiverType.getConstructor())) { 115 receiverType = typeParameter.getUpperBoundsAsType(); 116 } 117 } 118 List<TypeProjection> fakeTypeArguments = Lists.newArrayList(); 119 for (TypeProjection typeProjection : receiverType.getArguments()) { 120 fakeTypeArguments.add(new TypeProjectionImpl(typeProjection.getProjectionKind(), DONT_CARE)); 121 } 122 return new JetTypeImpl( 123 receiverType.getAnnotations(), receiverType.getConstructor(), receiverType.isMarkedNullable(), 124 fakeTypeArguments, ErrorUtils.createErrorScope("Error scope for erased receiver type", /*throwExceptions=*/true)); 125 } 126 127 public static boolean isOrOverridesSynthesized(@NotNull CallableMemberDescriptor descriptor) { 128 if (descriptor.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) { 129 return true; 130 } 131 if (descriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { 132 for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) { 133 if (!isOrOverridesSynthesized(overridden)) { 134 return false; 135 } 136 } 137 return true; 138 } 139 return false; 140 } 141 142 public static boolean isInvokeCallOnVariable(@NotNull Call call) { 143 if (call.getCallType() != Call.CallType.INVOKE) return false; 144 ReceiverValue dispatchReceiver = call.getDispatchReceiver(); 145 //calleeExpressionAsDispatchReceiver for invoke is always ExpressionReceiver, see CallForImplicitInvoke 146 JetExpression expression = ((ExpressionReceiver) dispatchReceiver).getExpression(); 147 return expression instanceof JetSimpleNameExpression; 148 } 149 150 public static boolean isInvokeCallOnExpressionWithBothReceivers(@NotNull Call call) { 151 if (call.getCallType() != Call.CallType.INVOKE || isInvokeCallOnVariable(call)) return false; 152 return call.getExplicitReceiver().exists() && call.getDispatchReceiver().exists(); 153 } 154 }