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.codegen.state; 018 019import com.intellij.psi.PsiElement; 020import org.jetbrains.annotations.NotNull; 021import org.jetbrains.annotations.Nullable; 022import org.jetbrains.asm4.Type; 023import org.jetbrains.jet.codegen.*; 024import org.jetbrains.jet.codegen.binding.BindingTraceAware; 025import org.jetbrains.jet.codegen.binding.CalculatedClosure; 026import org.jetbrains.jet.codegen.binding.CodegenBinding; 027import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor; 028import org.jetbrains.jet.codegen.signature.*; 029import org.jetbrains.jet.lang.descriptors.*; 030import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall; 031import org.jetbrains.jet.lang.psi.JetExpression; 032import org.jetbrains.jet.lang.psi.JetFile; 033import org.jetbrains.jet.lang.resolve.BindingContext; 034import org.jetbrains.jet.lang.resolve.BindingContextUtils; 035import org.jetbrains.jet.lang.resolve.BindingTrace; 036import org.jetbrains.jet.lang.resolve.DescriptorUtils; 037import org.jetbrains.jet.lang.resolve.java.*; 038import org.jetbrains.jet.lang.resolve.name.Name; 039import org.jetbrains.jet.lang.types.*; 040import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 041 042import java.util.ArrayList; 043import java.util.Collections; 044import java.util.List; 045import java.util.Map; 046 047import static org.jetbrains.asm4.Opcodes.*; 048import static org.jetbrains.jet.codegen.AsmUtil.boxType; 049import static org.jetbrains.jet.codegen.AsmUtil.getTraitImplThisParameterType; 050import static org.jetbrains.jet.codegen.CodegenUtil.*; 051import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionTraitClassName; 052import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; 053 054public class JetTypeMapper extends BindingTraceAware { 055 056 private final boolean mapBuiltinsToJava; 057 private final ClassBuilderMode classBuilderMode; 058 059 public JetTypeMapper(BindingTrace bindingTrace, boolean mapBuiltinsToJava, ClassBuilderMode mode) { 060 super(bindingTrace); 061 this.mapBuiltinsToJava = mapBuiltinsToJava; 062 classBuilderMode = mode; 063 } 064 065 @NotNull 066 public JvmClassName getOwner(DeclarationDescriptor descriptor, OwnerKind kind, boolean isInsideModule) { 067 JetTypeMapperMode mapTypeMode = ownerKindToMapTypeMode(kind); 068 069 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); 070 if (containingDeclaration instanceof NamespaceDescriptor) { 071 return jvmClassNameForNamespace((NamespaceDescriptor) containingDeclaration, descriptor, isInsideModule); 072 } 073 else if (containingDeclaration instanceof ClassDescriptor) { 074 ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; 075 if (classDescriptor.getKind() == ClassKind.OBJECT) { 076 mapTypeMode = JetTypeMapperMode.IMPL; 077 } 078 Type asmType = mapType(classDescriptor.getDefaultType(), mapTypeMode); 079 if (asmType.getSort() != Type.OBJECT) { 080 throw new IllegalStateException(); 081 } 082 return JvmClassName.byType(asmType); 083 } 084 else if (containingDeclaration instanceof ScriptDescriptor) { 085 return classNameForScriptDescriptor(bindingContext, (ScriptDescriptor) containingDeclaration); 086 } 087 else { 088 throw new UnsupportedOperationException("don't know how to generate owner for parent " + containingDeclaration); 089 } 090 } 091 092 private static JetTypeMapperMode ownerKindToMapTypeMode(OwnerKind kind) { 093 if (kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.NAMESPACE || kind instanceof OwnerKind.StaticDelegateKind) { 094 return JetTypeMapperMode.IMPL; 095 } 096 else if (kind == OwnerKind.TRAIT_IMPL) { 097 return JetTypeMapperMode.TRAIT_IMPL; 098 } 099 else { 100 throw new IllegalStateException("must not call this method with kind = " + kind); 101 } 102 } 103 104 @NotNull 105 private JavaNamespaceKind getNsKind(@NotNull NamespaceDescriptor ns) { 106 JavaNamespaceKind javaNamespaceKind = bindingContext.get(JavaBindingContext.JAVA_NAMESPACE_KIND, ns); 107 Boolean src = bindingContext.get(BindingContext.NAMESPACE_IS_SRC, ns); 108 109 if (javaNamespaceKind == null && src == null) { 110 throw new IllegalStateException("unknown namespace origin: " + ns); 111 } 112 113 if (javaNamespaceKind != null) { 114 if (javaNamespaceKind == JavaNamespaceKind.CLASS_STATICS && src != null) { 115 throw new IllegalStateException( 116 "conflicting namespace " + ns + ": it is both java statics and from src"); 117 } 118 return javaNamespaceKind; 119 } 120 else { 121 return JavaNamespaceKind.PROPER; 122 } 123 } 124 125 @NotNull 126 private JvmClassName jvmClassNameForNamespace( 127 @NotNull NamespaceDescriptor namespace, 128 @NotNull DeclarationDescriptor descriptor, 129 boolean insideModule 130 ) { 131 132 StringBuilder r = new StringBuilder(); 133 134 List<DeclarationDescriptor> path = DescriptorUtils.getPathWithoutRootNsAndModule(namespace); 135 136 for (DeclarationDescriptor pathElement : path) { 137 NamespaceDescriptor ns = (NamespaceDescriptor) pathElement; 138 if (r.length() > 0) { 139 JavaNamespaceKind nsKind = getNsKind((NamespaceDescriptor) ns.getContainingDeclaration()); 140 if (nsKind == JavaNamespaceKind.PROPER) { 141 r.append("/"); 142 } 143 else if (nsKind == JavaNamespaceKind.CLASS_STATICS) { 144 r.append("$"); 145 } 146 } 147 r.append(ns.getName()); 148 } 149 150 if (getNsKind(namespace) == JavaNamespaceKind.PROPER) { 151 if (r.length() > 0) { 152 r.append("/"); 153 } 154 155 JetFile file = BindingContextUtils.getContainingFile(bindingContext, descriptor); 156 if (insideModule && file != null) { 157 String internalName = NamespaceCodegen.getNamespacePartInternalName(file); 158 r.append(internalName.substring(r.length())); 159 } 160 else { 161 r.append(PackageClassUtils.getPackageClassName(namespace.getFqName())); 162 } 163 } 164 165 if (r.length() == 0) { 166 throw new IllegalStateException("internal error: failed to generate classname for " + namespace); 167 } 168 169 return JvmClassName.byInternalName(r.toString()); 170 } 171 172 @NotNull 173 public Type mapReturnType(@NotNull JetType jetType) { 174 return mapReturnType(jetType, null); 175 } 176 177 @NotNull 178 private Type mapReturnType(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor) { 179 if (jetType.equals(KotlinBuiltIns.getInstance().getUnitType())) { 180 if (signatureVisitor != null) { 181 signatureVisitor.writeAsmType(Type.VOID_TYPE, false); 182 } 183 return Type.VOID_TYPE; 184 } 185 else if (jetType.equals(KotlinBuiltIns.getInstance().getNothingType())) { 186 if (signatureVisitor != null) { 187 signatureVisitor.writeNothing(false); 188 } 189 return Type.VOID_TYPE; 190 } 191 if (jetType.equals(KotlinBuiltIns.getInstance().getNullableNothingType())) { 192 if (signatureVisitor != null) { 193 signatureVisitor.writeNothing(true); 194 } 195 return AsmTypeConstants.OBJECT_TYPE; 196 } 197 return mapType(jetType, signatureVisitor, JetTypeMapperMode.VALUE, Variance.OUT_VARIANCE); 198 } 199 200 @NotNull 201 public Type mapType(@NotNull JetType jetType, @NotNull JetTypeMapperMode kind) { 202 return mapType(jetType, null, kind); 203 } 204 205 @NotNull 206 public Type mapType(@NotNull JetType jetType) { 207 return mapType(jetType, null, JetTypeMapperMode.VALUE); 208 } 209 210 @NotNull 211 public Type mapType(@NotNull VariableDescriptor variableDescriptor) { 212 return mapType(variableDescriptor.getType(), null, JetTypeMapperMode.VALUE); 213 } 214 215 @NotNull 216 public Type mapType(@NotNull ClassifierDescriptor classifierDescriptor) { 217 return mapType(classifierDescriptor.getDefaultType()); 218 } 219 220 @NotNull 221 public Type mapType(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor, @NotNull JetTypeMapperMode kind) { 222 return mapType(jetType, signatureVisitor, kind, Variance.INVARIANT); 223 } 224 225 @NotNull 226 public Type mapType( 227 @NotNull JetType jetType, 228 @Nullable BothSignatureWriter signatureVisitor, 229 @NotNull JetTypeMapperMode kind, 230 @NotNull Variance howThisTypeIsUsed 231 ) { 232 Type known = null; 233 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); 234 235 if (mapBuiltinsToJava) { 236 if (descriptor instanceof ClassDescriptor) { 237 known = KotlinToJavaTypesMap.getInstance().getJavaAnalog(jetType); 238 } 239 } 240 241 if (known != null) { 242 if (kind == JetTypeMapperMode.VALUE) { 243 return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed); 244 } 245 else if (kind == JetTypeMapperMode.TYPE_PARAMETER) { 246 return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed); 247 } 248 else if (kind == JetTypeMapperMode.TRAIT_IMPL) { 249 throw new IllegalStateException("TRAIT_IMPL is not possible for " + jetType); 250 } 251 else if (kind == JetTypeMapperMode.IMPL) { 252 //noinspection ConstantConditions 253 if (mapBuiltinsToJava) { 254 // TODO: enable and fix tests 255 //throw new IllegalStateException("must not map known type to IMPL when not compiling builtins: " + jetType); 256 } 257 return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed); 258 } 259 else { 260 throw new IllegalStateException("unknown kind: " + kind); 261 } 262 } 263 264 TypeConstructor constructor = jetType.getConstructor(); 265 if (constructor instanceof IntersectionTypeConstructor) { 266 jetType = CommonSupertypes.commonSupertype(new ArrayList<JetType>(constructor.getSupertypes())); 267 } 268 269 if (descriptor == null) { 270 throw new UnsupportedOperationException("no descriptor for type constructor of " + jetType); 271 } 272 273 if (ErrorUtils.isError(descriptor)) { 274 if (classBuilderMode != ClassBuilderMode.SIGNATURES) { 275 throw new IllegalStateException(generateErrorMessageForErrorType(descriptor)); 276 } 277 Type asmType = Type.getObjectType("error/NonExistentClass"); 278 if (signatureVisitor != null) { 279 signatureVisitor.writeAsmType(asmType, true); 280 } 281 checkValidType(asmType); 282 return asmType; 283 } 284 285 if (mapBuiltinsToJava && descriptor instanceof ClassDescriptor && KotlinBuiltIns.getInstance().isArray(jetType)) { 286 if (jetType.getArguments().size() != 1) { 287 throw new UnsupportedOperationException("arrays must have one type argument"); 288 } 289 TypeProjection memberProjection = jetType.getArguments().get(0); 290 JetType memberType = memberProjection.getType(); 291 292 if (signatureVisitor != null) { 293 signatureVisitor.writeArrayType(jetType.isNullable(), memberProjection.getProjectionKind()); 294 mapType(memberType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER); 295 signatureVisitor.writeArrayEnd(); 296 } 297 298 Type r; 299 if (!isGenericsArray(jetType)) { 300 r = Type.getType("[" + boxType(mapType(memberType, kind)).getDescriptor()); 301 } 302 else { 303 r = AsmTypeConstants.JAVA_ARRAY_GENERIC_TYPE; 304 } 305 checkValidType(r); 306 return r; 307 } 308 309 if (descriptor instanceof ClassDescriptor) { 310 JvmClassName name = getJvmInternalName(bindingTrace, descriptor); 311 Type asmType; 312 if (kind == JetTypeMapperMode.TRAIT_IMPL) { 313 asmType = Type.getObjectType(name.getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX); 314 } 315 else { 316 asmType = name.getAsmType(); 317 } 318 boolean forceReal = KotlinToJavaTypesMap.getInstance().isForceReal(name); 319 320 writeGenericType(signatureVisitor, asmType, jetType, forceReal, howThisTypeIsUsed); 321 322 checkValidType(asmType); 323 return asmType; 324 } 325 326 if (descriptor instanceof TypeParameterDescriptor) { 327 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor; 328 Type type = mapType(typeParameterDescriptor.getUpperBoundsAsType(), kind); 329 if (signatureVisitor != null) { 330 signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), jetType.isNullable(), type); 331 } 332 checkValidType(type); 333 return type; 334 } 335 336 throw new UnsupportedOperationException("Unknown type " + jetType); 337 } 338 339 private String generateErrorMessageForErrorType(@NotNull DeclarationDescriptor descriptor) { 340 PsiElement declarationElement = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); 341 PsiElement parentDeclarationElement = null; 342 if (declarationElement != null) { 343 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); 344 if (containingDeclaration != null) { 345 parentDeclarationElement = BindingContextUtils.descriptorToDeclaration(bindingContext, containingDeclaration); 346 } 347 } 348 349 return String.format("Error types are not allowed when classBuilderMode = %s. For declaration %s:%s in %s:%s", 350 classBuilderMode, 351 declarationElement, 352 declarationElement != null ? declarationElement.getText() : "null", 353 parentDeclarationElement, 354 parentDeclarationElement != null ? parentDeclarationElement.getText() : "null"); 355 } 356 357 private void writeGenericType( 358 BothSignatureWriter signatureVisitor, 359 Type asmType, 360 JetType jetType, 361 boolean forceReal, 362 Variance howThisTypeIsUsed 363 ) { 364 if (signatureVisitor != null) { 365 String kotlinTypeName = getKotlinTypeNameForSignature(jetType, asmType); 366 signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable(), forceReal, kotlinTypeName); 367 368 List<TypeProjection> arguments = jetType.getArguments(); 369 for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) { 370 TypeProjection argument = arguments.get(parameter.getIndex()); 371 372 Variance projectionKindForKotlin = argument.getProjectionKind(); 373 Variance projectionKindForJava = getEffectiveVariance( 374 parameter.getVariance(), 375 projectionKindForKotlin, 376 howThisTypeIsUsed 377 ); 378 signatureVisitor.writeTypeArgument(projectionKindForKotlin, projectionKindForJava); 379 380 mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER); 381 signatureVisitor.writeTypeArgumentEnd(); 382 } 383 signatureVisitor.writeClassEnd(); 384 } 385 } 386 387 private static Variance getEffectiveVariance(Variance parameterVariance, Variance projectionKind, Variance howThisTypeIsUsed) { 388 // Return type must not contain wildcards 389 if (howThisTypeIsUsed == Variance.OUT_VARIANCE) return projectionKind; 390 391 if (parameterVariance == Variance.INVARIANT) { 392 return projectionKind; 393 } 394 if (projectionKind == Variance.INVARIANT) { 395 return parameterVariance; 396 } 397 if (parameterVariance == projectionKind) { 398 return parameterVariance; 399 } 400 401 // In<out X> = In<*> 402 // Out<in X> = Out<*> 403 return Variance.OUT_VARIANCE; 404 } 405 406 private Type mapKnownAsmType( 407 JetType jetType, 408 Type asmType, 409 @Nullable BothSignatureWriter signatureVisitor, 410 @NotNull Variance howThisTypeIsUsed 411 ) { 412 if (signatureVisitor != null) { 413 if (jetType.getArguments().isEmpty()) { 414 String kotlinTypeName = getKotlinTypeNameForSignature(jetType, asmType); 415 signatureVisitor.writeAsmType(asmType, jetType.isNullable(), kotlinTypeName); 416 } 417 else { 418 writeGenericType(signatureVisitor, asmType, jetType, false, howThisTypeIsUsed); 419 } 420 } 421 checkValidType(asmType); 422 return asmType; 423 } 424 425 @Nullable 426 private static String getKotlinTypeNameForSignature(@NotNull JetType jetType, @NotNull Type asmType) { 427 ClassifierDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); 428 if (descriptor == null) return null; 429 if (asmType.getSort() != Type.OBJECT) return null; 430 431 JvmClassName jvmClassName = JvmClassName.byType(asmType); 432 if (JavaToKotlinClassMap.getInstance().mapPlatformClass(jvmClassName.getFqName()).size() > 1) { 433 return JvmClassName.byClassDescriptor(descriptor).getSignatureName(); 434 } 435 return null; 436 } 437 438 private void checkValidType(@NotNull Type type) { 439 if (!mapBuiltinsToJava) { 440 String descriptor = type.getDescriptor(); 441 if (!descriptor.equals("Ljava/lang/Object;")) { 442 if (descriptor.startsWith("Ljava/")) { 443 throw new IllegalStateException("builtins must not reference java.* classes: " + descriptor); 444 } 445 } 446 } 447 } 448 449 @NotNull 450 public CallableMethod mapToCallableMethod( 451 @NotNull FunctionDescriptor functionDescriptor, 452 boolean superCall, 453 boolean isInsideClass, 454 boolean isInsideModule, 455 OwnerKind kind 456 ) { 457 DeclarationDescriptor functionParent = functionDescriptor.getOriginal().getContainingDeclaration(); 458 459 functionDescriptor = unwrapFakeOverride(functionDescriptor); 460 461 JvmMethodSignature descriptor = mapSignature(functionDescriptor.getOriginal(), true, kind); 462 JvmClassName owner; 463 JvmClassName ownerForDefaultImpl; 464 JvmClassName ownerForDefaultParam; 465 int invokeOpcode; 466 JvmClassName thisClass; 467 if (functionParent instanceof NamespaceDescriptor) { 468 assert !superCall; 469 owner = jvmClassNameForNamespace((NamespaceDescriptor) functionParent, functionDescriptor, isInsideModule); 470 ownerForDefaultImpl = ownerForDefaultParam = owner; 471 invokeOpcode = INVOKESTATIC; 472 thisClass = null; 473 } 474 else if (functionDescriptor instanceof ConstructorDescriptor) { 475 assert !superCall; 476 ClassDescriptor containingClass = (ClassDescriptor) functionParent; 477 owner = JvmClassName.byType(mapType(containingClass.getDefaultType(), JetTypeMapperMode.IMPL)); 478 ownerForDefaultImpl = ownerForDefaultParam = owner; 479 invokeOpcode = INVOKESPECIAL; 480 thisClass = null; 481 } 482 else if (functionParent instanceof ScriptDescriptor) { 483 thisClass = owner = 484 ownerForDefaultParam = ownerForDefaultImpl = classNameForScriptDescriptor(bindingContext, (ScriptDescriptor) functionParent); 485 invokeOpcode = INVOKEVIRTUAL; 486 } 487 else if (functionParent instanceof ClassDescriptor) { 488 489 FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor); 490 491 ClassDescriptor currentOwner = (ClassDescriptor) functionParent; 492 ClassDescriptor declarationOwner = (ClassDescriptor) declarationFunctionDescriptor.getContainingDeclaration(); 493 494 boolean originalIsInterface = isInterface(declarationOwner); 495 boolean currentIsInterface = isInterface(currentOwner); 496 497 boolean isAccessor = isAccessor(functionDescriptor); 498 499 ClassDescriptor receiver; 500 if (currentIsInterface && !originalIsInterface) { 501 receiver = declarationOwner; 502 } 503 else { 504 receiver = currentOwner; 505 } 506 507 // TODO: TYPE_PARAMETER is hack here 508 509 boolean isInterface = originalIsInterface && currentIsInterface; 510 Type type = mapType(receiver.getDefaultType(), JetTypeMapperMode.TYPE_PARAMETER); 511 owner = JvmClassName.byType(type); 512 513 ClassDescriptor declarationOwnerForDefault = (ClassDescriptor) findBaseDeclaration(functionDescriptor).getContainingDeclaration(); 514 ownerForDefaultParam = JvmClassName.byType(mapType(declarationOwnerForDefault.getDefaultType(), JetTypeMapperMode.TYPE_PARAMETER)); 515 ownerForDefaultImpl = JvmClassName.byInternalName( 516 ownerForDefaultParam.getInternalName() + (isInterface(declarationOwnerForDefault) ? JvmAbi.TRAIT_IMPL_SUFFIX : "")); 517 if (isInterface) { 518 invokeOpcode = superCall ? INVOKESTATIC : INVOKEINTERFACE; 519 } 520 else { 521 if (isAccessor) { 522 invokeOpcode = INVOKESTATIC; 523 } 524 else { 525 boolean isPrivateFunInvocation = isInsideClass && functionDescriptor.getVisibility() == Visibilities.PRIVATE; 526 invokeOpcode = superCall || isPrivateFunInvocation ? INVOKESPECIAL : INVOKEVIRTUAL; 527 } 528 } 529 530 if (isInterface && superCall) { 531 descriptor = mapSignature(functionDescriptor, false, OwnerKind.TRAIT_IMPL); 532 owner = JvmClassName.byInternalName(owner.getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX); 533 } 534 thisClass = JvmClassName.byType(mapType(receiver.getDefaultType())); 535 } 536 else { 537 throw new UnsupportedOperationException("unknown function parent"); 538 } 539 540 541 Type receiverParameterType; 542 ReceiverParameterDescriptor receiverParameter = functionDescriptor.getOriginal().getReceiverParameter(); 543 if (receiverParameter != null) { 544 receiverParameterType = mapType(receiverParameter.getType()); 545 } 546 else { 547 receiverParameterType = null; 548 } 549 return new CallableMethod( 550 owner, ownerForDefaultImpl, ownerForDefaultParam, descriptor, invokeOpcode, 551 thisClass, receiverParameterType, null); 552 } 553 554 public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) { 555 return descriptor instanceof AccessorForFunctionDescriptor || 556 descriptor instanceof AccessorForPropertyDescriptor || 557 descriptor instanceof AccessorForPropertyDescriptor.Getter || 558 descriptor instanceof AccessorForPropertyDescriptor.Setter; 559 } 560 561 @NotNull 562 private static FunctionDescriptor findAnyDeclaration(@NotNull FunctionDescriptor function) { 563 if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) { 564 return function; 565 } 566 return findBaseDeclaration(function); 567 } 568 569 @NotNull 570 private static FunctionDescriptor findBaseDeclaration(@NotNull FunctionDescriptor function) { 571 if (function.getOverriddenDescriptors().isEmpty()) { 572 return function; 573 } 574 else { 575 // TODO: prefer class to interface 576 return findBaseDeclaration(function.getOverriddenDescriptors().iterator().next()); 577 } 578 } 579 580 @NotNull 581 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, boolean needGenericSignature, @NotNull OwnerKind kind) { 582 String name = f.getName().asString(); 583 if (f instanceof PropertyAccessorDescriptor) { 584 boolean isGetter = f instanceof PropertyGetterDescriptor; 585 name = getPropertyAccessorName(((PropertyAccessorDescriptor) f).getCorrespondingProperty(), isGetter); 586 } 587 return mapSignature(name, f, needGenericSignature, kind); 588 } 589 590 @NotNull 591 public JvmMethodSignature mapSignature(@NotNull Name functionName, @NotNull FunctionDescriptor f) { 592 return mapSignature(functionName.asString(), f, false, OwnerKind.IMPLEMENTATION); 593 } 594 595 @NotNull 596 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f) { 597 return mapSignature(f.getName(), f); 598 } 599 600 @NotNull 601 private JvmMethodSignature mapSignature( 602 @NotNull String methodName, 603 @NotNull FunctionDescriptor f, 604 boolean needGenericSignature, 605 @NotNull OwnerKind kind 606 ) { 607 if (kind == OwnerKind.TRAIT_IMPL) { 608 needGenericSignature = false; 609 } 610 611 BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, needGenericSignature); 612 613 writeFormalTypeParameters(f.getTypeParameters(), signatureVisitor); 614 615 signatureVisitor.writeParametersStart(); 616 writeThisIfNeeded(f, kind, signatureVisitor); 617 writeReceiverIfNeeded(f.getReceiverParameter(), signatureVisitor); 618 619 for (ValueParameterDescriptor parameter : f.getValueParameters()) { 620 writeParameter(signatureVisitor, parameter.getType()); 621 } 622 623 signatureVisitor.writeParametersEnd(); 624 625 if (f instanceof ConstructorDescriptor) { 626 signatureVisitor.writeVoidReturn(); 627 } 628 else { 629 signatureVisitor.writeReturnType(); 630 JetType returnType = f.getReturnType(); 631 assert returnType != null : "Function " + f + " has no return type"; 632 mapReturnType(returnType, signatureVisitor); 633 signatureVisitor.writeReturnTypeEnd(); 634 } 635 636 return signatureVisitor.makeJvmMethodSignature(methodName); 637 } 638 639 @Nullable 640 public String mapFieldSignature(@NotNull JetType backingFieldType) { 641 BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE, true); 642 signatureVisitor.writeFieldTypeStart(); 643 mapType(backingFieldType, signatureVisitor, JetTypeMapperMode.VALUE); 644 signatureVisitor.writeFieldTypeEnd(); 645 return signatureVisitor.makeJavaGenericSignature(); 646 } 647 648 private void writeThisIfNeeded( 649 @NotNull CallableMemberDescriptor descriptor, 650 @NotNull OwnerKind kind, 651 @NotNull BothSignatureWriter signatureVisitor 652 ) { 653 if (kind == OwnerKind.TRAIT_IMPL) { 654 ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration(); 655 Type type = getTraitImplThisParameterType(containingDeclaration, this); 656 657 signatureVisitor.writeParameterType(JvmMethodParameterKind.THIS); 658 signatureVisitor.writeAsmType(type, false); 659 signatureVisitor.writeParameterTypeEnd(); 660 } 661 else { 662 writeThisForAccessorIfNeeded(descriptor, signatureVisitor); 663 } 664 } 665 666 private void writeThisForAccessorIfNeeded(@NotNull CallableMemberDescriptor descriptor, @NotNull BothSignatureWriter signatureVisitor) { 667 if (isAccessor(descriptor) && descriptor.getExpectedThisObject() != null) { 668 signatureVisitor.writeParameterType(JvmMethodParameterKind.THIS); 669 mapType(((ClassifierDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), signatureVisitor, JetTypeMapperMode.VALUE); 670 signatureVisitor.writeParameterTypeEnd(); 671 } 672 } 673 674 675 public void writeFormalTypeParameters(List<TypeParameterDescriptor> typeParameters, BothSignatureWriter signatureVisitor) { 676 if (signatureVisitor == null) { 677 return; 678 } 679 680 signatureVisitor.writeFormalTypeParametersStart(); 681 for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) { 682 writeFormalTypeParameter(typeParameterDescriptor, signatureVisitor); 683 } 684 signatureVisitor.writeFormalTypeParametersEnd(); 685 } 686 687 private void writeFormalTypeParameter(TypeParameterDescriptor typeParameterDescriptor, BothSignatureWriter signatureVisitor) { 688 signatureVisitor.writeFormalTypeParameter(typeParameterDescriptor.getName().asString(), typeParameterDescriptor.getVariance(), 689 typeParameterDescriptor.isReified()); 690 691 classBound: 692 { 693 signatureVisitor.writeClassBound(); 694 695 for (JetType jetType : typeParameterDescriptor.getUpperBounds()) { 696 if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) { 697 if (!isInterface(jetType)) { 698 mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER); 699 break classBound; 700 } 701 } 702 } 703 704 // "extends Object" is optional according to ClassFileFormat-Java5.pdf 705 // but javac complaints to signature: 706 // <P:>Ljava/lang/Object; 707 // TODO: avoid writing java/lang/Object if interface list is not empty 708 } 709 signatureVisitor.writeClassBoundEnd(); 710 711 for (JetType jetType : typeParameterDescriptor.getUpperBounds()) { 712 if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) { 713 if (isInterface(jetType)) { 714 signatureVisitor.writeInterfaceBound(); 715 mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER); 716 signatureVisitor.writeInterfaceBoundEnd(); 717 } 718 } 719 if (jetType.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) { 720 signatureVisitor.writeInterfaceBound(); 721 mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER); 722 signatureVisitor.writeInterfaceBoundEnd(); 723 } 724 } 725 726 signatureVisitor.writeFormalTypeParameterEnd(); 727 } 728 729 730 private void writeReceiverIfNeeded(@Nullable ReceiverParameterDescriptor receiver, BothSignatureWriter signatureWriter) { 731 if (receiver != null) { 732 signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER); 733 mapType(receiver.getType(), signatureWriter, JetTypeMapperMode.VALUE); 734 signatureWriter.writeParameterTypeEnd(); 735 } 736 } 737 738 @NotNull 739 public static String getPropertyAccessorName(@NotNull PropertyDescriptor descriptor, boolean isGetter) { 740 DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration(); 741 boolean isAnnotation = parentDescriptor instanceof ClassDescriptor && 742 ((ClassDescriptor) parentDescriptor).getKind() == ClassKind.ANNOTATION_CLASS; 743 return isAnnotation ? descriptor.getName().asString() : 744 isGetter ? PropertyCodegen.getterName(descriptor.getName()) : PropertyCodegen.setterName(descriptor.getName()); 745 } 746 747 @NotNull 748 public JvmPropertyAccessorSignature mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) { 749 // TODO: do not genClassOrObject generics if not needed 750 BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true); 751 752 writeFormalTypeParameters(descriptor.getTypeParameters(), signatureWriter); 753 754 signatureWriter.writeParametersStart(); 755 writeThisIfNeeded(descriptor, kind, signatureWriter); 756 writeReceiverIfNeeded(descriptor.getReceiverParameter(), signatureWriter); 757 signatureWriter.writeParametersEnd(); 758 759 signatureWriter.writeReturnType(); 760 mapType(descriptor.getType(), signatureWriter, JetTypeMapperMode.VALUE, Variance.OUT_VARIANCE); 761 signatureWriter.writeReturnTypeEnd(); 762 763 String name = getPropertyAccessorName(descriptor, true); 764 return signatureWriter.makeJvmPropertyAccessorSignature(name, true); 765 } 766 767 768 @NotNull 769 public JvmPropertyAccessorSignature mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) { 770 assert descriptor.isVar(); 771 772 // TODO: generics signature is not always needed 773 BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true); 774 775 writeFormalTypeParameters(descriptor.getTypeParameters(), signatureWriter); 776 777 signatureWriter.writeParametersStart(); 778 writeThisIfNeeded(descriptor, kind, signatureWriter); 779 writeReceiverIfNeeded(descriptor.getReceiverParameter(), signatureWriter); 780 writeParameter(signatureWriter, descriptor.getType()); 781 signatureWriter.writeParametersEnd(); 782 783 signatureWriter.writeVoidReturn(); 784 785 String name = getPropertyAccessorName(descriptor, false); 786 return signatureWriter.makeJvmPropertyAccessorSignature(name, false); 787 } 788 789 private void writeParameter(@NotNull BothSignatureWriter signatureWriter, @NotNull JetType outType) { 790 signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE); 791 mapType(outType, signatureWriter, JetTypeMapperMode.VALUE); 792 signatureWriter.writeParameterTypeEnd(); 793 } 794 795 @NotNull 796 public JvmMethodSignature mapConstructorSignature(@NotNull ConstructorDescriptor descriptor) { 797 return mapConstructorSignature(descriptor, bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration())); 798 } 799 800 @NotNull 801 public JvmMethodSignature mapConstructorSignature(@NotNull ConstructorDescriptor descriptor, @Nullable CalculatedClosure closure) { 802 803 BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true); 804 805 // constructor type parmeters are fake 806 writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), signatureWriter); 807 808 signatureWriter.writeParametersStart(); 809 810 ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration(); 811 ClassDescriptor captureThis = closure != null ? closure.getCaptureThis() : null; 812 if (captureThis != null) { 813 signatureWriter.writeParameterType(JvmMethodParameterKind.OUTER); 814 mapType(captureThis.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE); 815 signatureWriter.writeParameterTypeEnd(); 816 } 817 818 ClassifierDescriptor captureReceiver = closure != null ? closure.getCaptureReceiver() : null; 819 if (captureReceiver != null) { 820 signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER); 821 mapType(captureReceiver.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE); 822 signatureWriter.writeParameterTypeEnd(); 823 } 824 825 if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) { 826 signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_NAME); 827 mapType(KotlinBuiltIns.getInstance().getStringType(), signatureWriter, JetTypeMapperMode.VALUE); 828 signatureWriter.writeParameterTypeEnd(); 829 signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_ORDINAL); 830 mapType(KotlinBuiltIns.getInstance().getIntType(), signatureWriter, JetTypeMapperMode.VALUE); 831 signatureWriter.writeParameterTypeEnd(); 832 } 833 834 if (closure != null) { 835 for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) { 836 DeclarationDescriptor variableDescriptor = entry.getKey(); 837 Type type = null; 838 if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) { 839 Type sharedVarType = getSharedVarType(variableDescriptor); 840 if (sharedVarType == null) { 841 sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType()); 842 } 843 type = sharedVarType; 844 } 845 else if (isLocalNamedFun(variableDescriptor)) { 846 type = classNameForAnonymousClass(bindingContext, (FunctionDescriptor) variableDescriptor).getAsmType(); 847 } 848 849 if (type != null) { 850 signatureWriter.writeParameterType(JvmMethodParameterKind.SHARED_VAR); 851 signatureWriter.writeAsmType(type, false); 852 signatureWriter.writeParameterTypeEnd(); 853 } 854 } 855 856 JetDelegatorToSuperCall superCall = closure.getSuperCall(); 857 if (superCall != null) { 858 DeclarationDescriptor superDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, 859 superCall 860 .getCalleeExpression() 861 .getConstructorReferenceExpression()); 862 863 if(superDescriptor instanceof ConstructorDescriptor) { 864 ConstructorDescriptor superConstructor = (ConstructorDescriptor) superDescriptor; 865 866 if (isObjectLiteral(bindingContext, descriptor.getContainingDeclaration())) { 867 List<JvmMethodParameterSignature> types = mapConstructorSignature(superConstructor).getKotlinParameterTypes(); 868 if (types != null) { 869 for (JvmMethodParameterSignature type : types) { 870 signatureWriter.writeParameterType(JvmMethodParameterKind.SUPER_CALL_PARAM); 871 signatureWriter.writeAsmType(type.getAsmType(), false); 872 signatureWriter.writeParameterTypeEnd(); 873 } 874 } 875 } 876 } 877 } 878 } 879 880 for (ValueParameterDescriptor parameter : descriptor.getOriginal().getValueParameters()) { 881 writeParameter(signatureWriter, parameter.getType()); 882 } 883 884 signatureWriter.writeParametersEnd(); 885 886 signatureWriter.writeVoidReturn(); 887 888 return signatureWriter.makeJvmMethodSignature("<init>"); 889 } 890 891 @NotNull 892 public JvmMethodSignature mapScriptSignature(@NotNull ScriptDescriptor script, @NotNull List<ScriptDescriptor> importedScripts) { 893 BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false); 894 895 writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), signatureWriter); 896 897 signatureWriter.writeParametersStart(); 898 899 for (ScriptDescriptor importedScript : importedScripts) { 900 signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE); 901 ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_SCRIPT, importedScript); 902 assert descriptor != null; 903 mapType(descriptor.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE); 904 signatureWriter.writeParameterTypeEnd(); 905 } 906 907 for (ValueParameterDescriptor valueParameter : script.getValueParameters()) { 908 writeParameter(signatureWriter, valueParameter.getType()); 909 } 910 911 signatureWriter.writeParametersEnd(); 912 913 signatureWriter.writeVoidReturn(); 914 915 return signatureWriter.makeJvmMethodSignature("<init>"); 916 } 917 918 @NotNull 919 public CallableMethod mapToCallableMethod(@NotNull ConstructorDescriptor descriptor) { 920 return mapToCallableMethod(descriptor, bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration())); 921 } 922 923 @NotNull 924 public CallableMethod mapToCallableMethod(@NotNull ConstructorDescriptor descriptor, @Nullable CalculatedClosure closure) { 925 JvmMethodSignature method = mapConstructorSignature(descriptor, closure); 926 JetType defaultType = descriptor.getContainingDeclaration().getDefaultType(); 927 Type mapped = mapType(defaultType, JetTypeMapperMode.IMPL); 928 if (mapped.getSort() != Type.OBJECT) { 929 throw new IllegalStateException("type must have been mapped to object: " + defaultType + ", actual: " + mapped); 930 } 931 JvmClassName owner = JvmClassName.byType(mapped); 932 return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL, null, null, null); 933 } 934 935 936 private static boolean isGenericsArray(JetType type) { 937 return KotlinBuiltIns.getInstance().isArray(type) && 938 type.getArguments().get(0).getType().getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor; 939 } 940 941 public Type getSharedVarType(DeclarationDescriptor descriptor) { 942 if (descriptor instanceof PropertyDescriptor) { 943 return StackValue 944 .sharedTypeForType(mapType(((PropertyDescriptor) descriptor).getReceiverParameter().getType())); 945 } 946 else if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) { 947 return classNameForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor).getAsmType(); 948 } 949 else if (descriptor instanceof FunctionDescriptor) { 950 return StackValue 951 .sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType())); 952 } 953 else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) { 954 JetType outType = ((VariableDescriptor) descriptor).getType(); 955 return StackValue.sharedTypeForType(mapType(outType)); 956 } 957 return null; 958 } 959 960 @NotNull 961 public CallableMethod mapToFunctionInvokeCallableMethod(@NotNull FunctionDescriptor fd) { 962 JvmMethodSignature descriptor = erasedInvokeSignature(fd); 963 JvmClassName owner = getFunctionTraitClassName(fd); 964 Type receiverParameterType; 965 ReceiverParameterDescriptor receiverParameter = fd.getOriginal().getReceiverParameter(); 966 if (receiverParameter != null) { 967 receiverParameterType = mapType(receiverParameter.getType()); 968 } 969 else { 970 receiverParameterType = null; 971 } 972 return new CallableMethod(owner, null, null, descriptor, INVOKEINTERFACE, owner, receiverParameterType, owner.getAsmType()); 973 } 974 975 @NotNull 976 public Type expressionType(JetExpression expr) { 977 JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expr); 978 return asmTypeOrVoid(type); 979 } 980 981 @NotNull 982 private Type asmTypeOrVoid(@Nullable JetType type) { 983 return type == null ? Type.VOID_TYPE : mapType(type); 984 } 985}