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 017package org.jetbrains.jet.lang.resolve.java.resolver; 018 019import com.google.common.collect.Lists; 020import com.google.common.collect.Sets; 021import com.intellij.openapi.diagnostic.Logger; 022import com.intellij.psi.PsiClass; 023import com.intellij.psi.PsiMethod; 024import com.intellij.psi.PsiType; 025import com.intellij.psi.util.PsiFormatUtil; 026import com.intellij.util.containers.ContainerUtil; 027import org.jetbrains.annotations.NotNull; 028import org.jetbrains.annotations.Nullable; 029import org.jetbrains.jet.lang.descriptors.*; 030import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent; 031import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; 032import org.jetbrains.jet.lang.resolve.*; 033import org.jetbrains.jet.lang.resolve.java.*; 034import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode; 035import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeMethodSignatureData; 036import org.jetbrains.jet.lang.resolve.java.kotlinSignature.SignaturesPropagationData; 037import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils; 038import org.jetbrains.jet.lang.resolve.java.provider.*; 039import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper; 040import org.jetbrains.jet.lang.resolve.name.Name; 041import org.jetbrains.jet.lang.resolve.scopes.JetScope; 042import org.jetbrains.jet.lang.types.*; 043import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 044 045import javax.inject.Inject; 046import java.util.Collections; 047import java.util.HashSet; 048import java.util.List; 049import java.util.Set; 050 051import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; 052import static org.jetbrains.jet.lang.resolve.OverridingUtil.*; 053import static org.jetbrains.jet.lang.resolve.java.provider.DeclarationOrigin.JAVA; 054import static org.jetbrains.jet.lang.resolve.java.provider.DeclarationOrigin.KOTLIN; 055import static org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils.*; 056 057public final class JavaFunctionResolver { 058 private static final Logger LOG = Logger.getInstance(JavaFunctionResolver.class); 059 060 private JavaTypeTransformer typeTransformer; 061 private BindingTrace trace; 062 private JavaSignatureResolver signatureResolver; 063 private JavaValueParameterResolver parameterResolver; 064 private JavaAnnotationResolver annotationResolver; 065 066 public JavaFunctionResolver() { 067 } 068 069 @Inject 070 public void setTypeTransformer(JavaTypeTransformer typeTransformer) { 071 this.typeTransformer = typeTransformer; 072 } 073 074 @Inject 075 public void setTrace(BindingTrace trace) { 076 this.trace = trace; 077 } 078 079 @Inject 080 public void setSignatureResolver(JavaSignatureResolver signatureResolver) { 081 this.signatureResolver = signatureResolver; 082 } 083 084 @Inject 085 public void setParameterResolver(JavaValueParameterResolver parameterResolver) { 086 this.parameterResolver = parameterResolver; 087 } 088 089 @Inject 090 public void setAnnotationResolver(JavaAnnotationResolver annotationResolver) { 091 this.annotationResolver = annotationResolver; 092 } 093 094 @Nullable 095 SimpleFunctionDescriptor resolveFunctionMutely( 096 @NotNull PsiMethodWrapper method, 097 @NotNull ClassOrNamespaceDescriptor ownerDescriptor 098 ) { 099 PsiClass containingClass = method.getPsiMethod().getContainingClass(); 100 assert containingClass != null : "containing class is null for " + method; 101 return resolveMethodToFunctionDescriptor(containingClass, method, DeclarationOrigin.JAVA, ownerDescriptor, false); 102 } 103 104 @Nullable 105 private SimpleFunctionDescriptor resolveMethodToFunctionDescriptor( 106 @NotNull PsiClass psiClass, PsiMethodWrapper method, 107 @NotNull DeclarationOrigin declarationOrigin, @NotNull ClassOrNamespaceDescriptor ownerDescriptor, boolean record 108 ) { 109 if (!DescriptorResolverUtils.isCorrectOwnerForEnumMember(ownerDescriptor, method.getPsiMember())) { 110 return null; 111 } 112 113 PsiType returnPsiType = method.getReturnType(); 114 if (returnPsiType == null) { 115 return null; 116 } 117 118 // TODO: ugly 119 if (method.getJetMethodAnnotation().hasPropertyFlag()) { 120 return null; 121 } 122 123 PsiMethod psiMethod = method.getPsiMethod(); 124 PsiClass containingClass = psiMethod.getContainingClass(); 125 if (declarationOrigin == KOTLIN) { 126 // TODO: unless maybe class explicitly extends Object 127 assert containingClass != null; 128 String ownerClassName = containingClass.getQualifiedName(); 129 if (DescriptorResolverUtils.OBJECT_FQ_NAME.asString().equals(ownerClassName)) { 130 return null; 131 } 132 } 133 134 if (trace.get(BindingContext.FUNCTION, psiMethod) != null) { 135 return trace.get(BindingContext.FUNCTION, psiMethod); 136 } 137 138 SimpleFunctionDescriptorImpl functionDescriptorImpl = new SimpleFunctionDescriptorImpl( 139 ownerDescriptor, 140 annotationResolver.resolveAnnotations(psiMethod), 141 Name.identifier(method.getName()), 142 DescriptorKindUtils.flagsToKind(method.getJetMethodAnnotation().kind()) 143 ); 144 145 String context = "method " + method.getName() + " in class " + psiClass.getQualifiedName(); 146 147 List<TypeParameterDescriptor> methodTypeParameters = 148 signatureResolver.resolveMethodTypeParameters(method, 149 functionDescriptorImpl); 150 151 TypeVariableResolver methodTypeVariableResolver = TypeVariableResolvers.typeVariableResolverFromTypeParameters(methodTypeParameters, 152 functionDescriptorImpl, 153 context); 154 155 JavaDescriptorResolver.ValueParameterDescriptors valueParameterDescriptors = parameterResolver 156 .resolveParameterDescriptors(functionDescriptorImpl, method.getParameters(), methodTypeVariableResolver); 157 JetType returnType = makeReturnType(returnPsiType, method, methodTypeVariableResolver); 158 159 List<String> signatureErrors = Lists.newArrayList(); 160 161 List<FunctionDescriptor> superFunctions; 162 if (ownerDescriptor instanceof ClassDescriptor && !method.getJetMethodAnnotation().isDefined()) { // don't propagate for Kotlin functions 163 SignaturesPropagationData signaturesPropagationData = new SignaturesPropagationData( 164 (ClassDescriptor) ownerDescriptor, returnType, valueParameterDescriptors, methodTypeParameters, method, trace); 165 superFunctions = signaturesPropagationData.getSuperFunctions(); 166 167 returnType = signaturesPropagationData.getModifiedReturnType(); 168 valueParameterDescriptors = signaturesPropagationData.getModifiedValueParameters(); 169 methodTypeParameters = signaturesPropagationData.getModifiedTypeParameters(); 170 171 signatureErrors.addAll(signaturesPropagationData.getSignatureErrors()); 172 } 173 else { 174 superFunctions = Collections.emptyList(); 175 } 176 177 AlternativeMethodSignatureData alternativeMethodSignatureData = 178 new AlternativeMethodSignatureData(method, valueParameterDescriptors, returnType, methodTypeParameters, 179 !superFunctions.isEmpty()); 180 if (alternativeMethodSignatureData.isAnnotated() && !alternativeMethodSignatureData.hasErrors()) { 181 valueParameterDescriptors = alternativeMethodSignatureData.getValueParameters(); 182 returnType = alternativeMethodSignatureData.getReturnType(); 183 methodTypeParameters = alternativeMethodSignatureData.getTypeParameters(); 184 } 185 else if (alternativeMethodSignatureData.hasErrors()) { 186 signatureErrors.add(alternativeMethodSignatureData.getError()); 187 } 188 189 functionDescriptorImpl.initialize( 190 valueParameterDescriptors.getReceiverType(), 191 DescriptorUtils.getExpectedThisObjectIfNeeded(ownerDescriptor), 192 methodTypeParameters, 193 valueParameterDescriptors.getDescriptors(), 194 returnType, 195 DescriptorResolverUtils.resolveModality(method, method.isFinal()), 196 DescriptorResolverUtils.resolveVisibility(psiMethod, method.getJetMethodAnnotation()), 197 /*isInline = */ false 198 ); 199 200 if (functionDescriptorImpl.getKind() == CallableMemberDescriptor.Kind.DECLARATION && record) { 201 BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, psiMethod, functionDescriptorImpl); 202 } 203 204 if (declarationOrigin == JAVA && record) { 205 trace.record(JavaBindingContext.IS_DECLARED_IN_JAVA, functionDescriptorImpl); 206 } 207 208 if (containingClass != psiClass && !method.isStatic()) { 209 throw new IllegalStateException("non-static method in subclass"); 210 } 211 212 if (!RawTypesCheck.hasRawTypesInHierarchicalSignature(psiMethod) 213 && JavaMethodSignatureUtil.isMethodReturnTypeCompatible(psiMethod) 214 && !containsErrorType(superFunctions, functionDescriptorImpl)) { 215 if (signatureErrors.isEmpty()) { 216 checkFunctionsOverrideCorrectly(method, superFunctions, functionDescriptorImpl); 217 } 218 else { 219 if (record) { 220 trace.record(JavaBindingContext.LOAD_FROM_JAVA_SIGNATURE_ERRORS, functionDescriptorImpl, signatureErrors); 221 } 222 } 223 } 224 225 return functionDescriptorImpl; 226 } 227 228 private static void checkFunctionsOverrideCorrectly( 229 PsiMethodWrapper method, 230 List<FunctionDescriptor> superFunctions, 231 FunctionDescriptor functionDescriptor 232 ) { 233 for (FunctionDescriptor superFunction : superFunctions) { 234 ClassDescriptor klass = (ClassDescriptor) functionDescriptor.getContainingDeclaration(); 235 List<TypeSubstitution> substitutions = Lists.newArrayList(); 236 while (true) { 237 substitutions.add(SubstitutionUtils.buildDeepSubstitutor(klass.getDefaultType()).getSubstitution()); 238 if (!klass.isInner()) { 239 break; 240 } 241 klass = (ClassDescriptor) klass.getContainingDeclaration(); 242 } 243 TypeSubstitutor substitutor = TypeSubstitutor.create(substitutions.toArray(new TypeSubstitution[substitutions.size()])); 244 FunctionDescriptor superFunctionSubstituted = superFunction.substitute(substitutor); 245 246 assert superFunctionSubstituted != null : 247 "Couldn't substitute super function: " + superFunction + ", substitutor = " + substitutor; 248 249 OverrideCompatibilityInfo.Result overridableResult = 250 isOverridableBy(superFunctionSubstituted, functionDescriptor).getResult(); 251 boolean paramsOk = overridableResult == OverrideCompatibilityInfo.Result.OVERRIDABLE; 252 boolean returnTypeOk = 253 isReturnTypeOkForOverride(JetTypeChecker.INSTANCE, superFunctionSubstituted, functionDescriptor); 254 if (!paramsOk || !returnTypeOk) { 255 LOG.error("Loaded Java method overrides another, but resolved as Kotlin function, doesn't.\n" 256 + "super function = " + superFunction + "\n" 257 + "super class = " + superFunction.getContainingDeclaration() + "\n" 258 + "sub function = " + functionDescriptor + "\n" 259 + "sub class = " + functionDescriptor.getContainingDeclaration() + "\n" 260 + "sub method = " + PsiFormatUtil.getExternalName(method.getPsiMethod()) + "\n" 261 + "@KotlinSignature = " + method.getSignatureAnnotation().signature()); 262 } 263 } 264 } 265 266 @NotNull 267 private Set<FunctionDescriptor> resolveNamedGroupFunctions( 268 @NotNull ClassOrNamespaceDescriptor owner, @NotNull PsiClass psiClass, 269 NamedMembers namedMembers, Name methodName, PsiDeclarationProvider scopeData 270 ) { 271 272 Set<SimpleFunctionDescriptor> functionsFromSupertypes = null; 273 if (owner instanceof ClassDescriptor) { 274 functionsFromSupertypes = getFunctionsFromSupertypes(methodName, owner); 275 } 276 277 Set<SimpleFunctionDescriptor> functionsFromCurrent = Sets.newHashSet(); 278 for (PsiMethodWrapper method : namedMembers.getMethods()) { 279 SimpleFunctionDescriptor function = resolveMethodToFunctionDescriptor(psiClass, method, scopeData.getDeclarationOrigin(), owner, true); 280 if (function != null) { 281 functionsFromCurrent.add(function); 282 283 if (!DescriptorResolverUtils.isKotlinClass(psiClass)) { 284 ContainerUtil.addIfNotNull(functionsFromCurrent, resolveSamAdapter(function)); 285 } 286 } 287 } 288 289 if (owner instanceof NamespaceDescriptor) { 290 ContainerUtil.addIfNotNull(functionsFromCurrent, resolveSamConstructor((NamespaceDescriptor) owner, namedMembers)); 291 } 292 293 294 final Set<FunctionDescriptor> fakeOverrides = new HashSet<FunctionDescriptor>(); 295 if (owner instanceof ClassDescriptor) { 296 ClassDescriptor classDescriptor = (ClassDescriptor) owner; 297 298 OverrideResolver.generateOverridesInFunctionGroup(methodName, functionsFromSupertypes, functionsFromCurrent, classDescriptor, 299 new OverrideResolver.DescriptorSink() { 300 @Override 301 public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) { 302 fakeOverrides.add((FunctionDescriptor) fakeOverride); 303 } 304 305 @Override 306 public void conflict( 307 @NotNull CallableMemberDescriptor fromSuper, 308 @NotNull CallableMemberDescriptor fromCurrent 309 ) { 310 // nop 311 } 312 }); 313 } 314 315 OverrideResolver.resolveUnknownVisibilities(fakeOverrides, trace); 316 317 Set<FunctionDescriptor> functions = Sets.newHashSet(fakeOverrides); 318 if (isEnumClassObject(owner)) { 319 for (FunctionDescriptor functionDescriptor : functionsFromCurrent) { 320 if (!(isEnumValueOfMethod(functionDescriptor) || isEnumValuesMethod(functionDescriptor))) { 321 functions.add(functionDescriptor); 322 } 323 } 324 } 325 else { 326 functions.addAll(functionsFromCurrent); 327 } 328 329 return functions; 330 } 331 332 @Nullable 333 private static ClassDescriptorFromJvmBytecode findClassInScope(@NotNull JetScope memberScope, @NotNull Name name) { 334 ClassifierDescriptor classifier = memberScope.getClassifier(name); 335 if (classifier instanceof ClassDescriptorFromJvmBytecode) { 336 return (ClassDescriptorFromJvmBytecode) classifier; 337 } 338 return null; 339 } 340 341 // E.g. we have foo.Bar.Baz class declared in Java. It will produce the following descriptors structure: 342 // namespace foo 343 // +-- class Bar 344 // | +-- class Baz 345 // +-- namespace Bar 346 // We need to find class 'Baz' in namespace 'foo.Bar'. 347 @Nullable 348 private static ClassDescriptorFromJvmBytecode findClassInNamespace(@NotNull NamespaceDescriptor namespace, @NotNull Name name) { 349 // First, try to find in namespace directly 350 ClassDescriptorFromJvmBytecode found = findClassInScope(namespace.getMemberScope(), name); 351 if (found != null) { 352 return found; 353 } 354 355 // If unsuccessful, try to find class of the same name as current (class 'foo.Bar') 356 NamespaceDescriptorParent parent = namespace.getContainingDeclaration(); 357 if (parent instanceof NamespaceDescriptor) { 358 // Calling recursively, looking for 'Bar' in 'foo' 359 ClassDescriptor classForCurrentNamespace = findClassInNamespace((NamespaceDescriptor) parent, namespace.getName()); 360 if (classForCurrentNamespace == null) { 361 return null; 362 } 363 364 // Try to find nested class 'Baz' in class 'foo.Bar' 365 return findClassInScope(DescriptorUtils.getStaticNestedClassesScope(classForCurrentNamespace), name); 366 } 367 return null; 368 } 369 370 @Nullable 371 private SimpleFunctionDescriptor resolveSamConstructor( 372 @NotNull NamespaceDescriptor ownerDescriptor, 373 @NotNull NamedMembers namedMembers 374 ) { 375 PsiClass samInterface = namedMembers.getSamInterface(); 376 if (samInterface != null) { 377 ClassDescriptorFromJvmBytecode klass = findClassInNamespace(ownerDescriptor, namedMembers.getName()); 378 if (klass != null) { 379 return recordSamConstructor(klass, createSamConstructorFunction(ownerDescriptor, klass), trace); 380 } 381 } 382 return null; 383 } 384 385 @Nullable 386 private SimpleFunctionDescriptor resolveSamAdapter(@NotNull SimpleFunctionDescriptor original) { 387 return isSamAdapterNecessary(original) 388 ? recordSamAdapter(original, createSamAdapterFunction(original), trace) 389 : null; 390 } 391 392 @NotNull 393 public Set<FunctionDescriptor> resolveFunctionGroup( 394 @NotNull Name methodName, 395 @NotNull ClassPsiDeclarationProvider scopeData, 396 @NotNull ClassOrNamespaceDescriptor ownerDescriptor 397 ) { 398 399 NamedMembers namedMembers = scopeData.getMembersCache().get(methodName); 400 if (namedMembers == null) { 401 return Collections.emptySet(); 402 } 403 PsiClass psiClass = scopeData.getPsiClass(); 404 return resolveNamedGroupFunctions(ownerDescriptor, psiClass, namedMembers, methodName, scopeData); 405 } 406 407 @NotNull 408 public Set<FunctionDescriptor> resolveFunctionGroup( 409 @NotNull Name functionName, 410 @NotNull PackagePsiDeclarationProvider scopeData, 411 @NotNull NamespaceDescriptor ownerDescriptor 412 ) { 413 NamedMembers namedMembers = scopeData.getMembersCache().get(functionName); 414 if (namedMembers != null) { 415 SimpleFunctionDescriptor samConstructor = resolveSamConstructor(ownerDescriptor, namedMembers); 416 if (samConstructor != null) { 417 return Collections.<FunctionDescriptor>singleton(samConstructor); 418 } 419 } 420 return Collections.emptySet(); 421 } 422 423 @NotNull 424 private JetType makeReturnType( 425 PsiType returnType, PsiMethodWrapper method, 426 @NotNull TypeVariableResolver typeVariableResolver 427 ) { 428 429 String returnTypeFromAnnotation = method.getJetMethodAnnotation().returnType(); 430 431 JetType transformedType; 432 if (returnTypeFromAnnotation.length() > 0) { 433 transformedType = typeTransformer.transformToType(returnTypeFromAnnotation, typeVariableResolver); 434 } 435 else { 436 TypeUsage typeUsage = JavaTypeTransformer.adjustTypeUsageWithMutabilityAnnotations(method.getPsiMethod(), TypeUsage.MEMBER_SIGNATURE_COVARIANT); 437 transformedType = typeTransformer.transformToType(returnType, typeUsage, typeVariableResolver); 438 } 439 440 if (JavaAnnotationResolver.findAnnotationWithExternal(method.getPsiMethod(), JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().asString()) != 441 null) { 442 return TypeUtils.makeNullableAsSpecified(transformedType, false); 443 } 444 else { 445 return transformedType; 446 } 447 } 448 449 @NotNull 450 private static Set<SimpleFunctionDescriptor> getFunctionsFromSupertypes( 451 @NotNull Name methodName, @NotNull ClassOrNamespaceDescriptor classOrNamespaceDescriptor 452 ) { 453 Set<SimpleFunctionDescriptor> r = Sets.newLinkedHashSet(); 454 for (JetType supertype : DescriptorResolverUtils.getSupertypes(classOrNamespaceDescriptor)) { 455 for (FunctionDescriptor function : supertype.getMemberScope().getFunctions(methodName)) { 456 r.add((SimpleFunctionDescriptor) function); 457 } 458 } 459 return r; 460 } 461 462 private static boolean containsErrorType(@NotNull List<FunctionDescriptor> superFunctions, @NotNull FunctionDescriptor function) { 463 if (containsErrorType(function)) { 464 return true; 465 } 466 467 for (FunctionDescriptor superFunction : superFunctions) { 468 if (containsErrorType(superFunction)) { 469 return true; 470 } 471 } 472 473 return false; 474 } 475 476 private static boolean containsErrorType(@NotNull FunctionDescriptor function) { 477 if (ErrorUtils.containsErrorType(function.getReturnType())) { 478 return true; 479 } 480 for (ValueParameterDescriptor parameter : function.getValueParameters()) { 481 if (ErrorUtils.containsErrorType(parameter.getType())) { 482 return true; 483 } 484 } 485 for (TypeParameterDescriptor parameter : function.getTypeParameters()) { 486 for (JetType upperBound : parameter.getUpperBounds()) { 487 if (ErrorUtils.containsErrorType(upperBound)) { 488 return true; 489 } 490 } 491 } 492 493 return false; 494 } 495 496 private static SimpleFunctionDescriptor recordSamConstructor(ClassDescriptorFromJvmBytecode klass, SimpleFunctionDescriptor constructorFunction, BindingTrace trace) { 497 trace.record(JavaBindingContext.SAM_CONSTRUCTOR_TO_INTERFACE, constructorFunction, klass); 498 trace.record(BindingContext.SOURCE_DESCRIPTOR_FOR_SYNTHESIZED, constructorFunction, klass); 499 return constructorFunction; 500 } 501 502 static <F extends FunctionDescriptor> F recordSamAdapter(F original, F adapterFunction, BindingTrace trace) { 503 trace.record(JavaBindingContext.SAM_ADAPTER_FUNCTION_TO_ORIGINAL, adapterFunction, original); 504 trace.record(BindingContext.SOURCE_DESCRIPTOR_FOR_SYNTHESIZED, adapterFunction, original); 505 return adapterFunction; 506 } 507}