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.codegen.state;
018
019 import com.intellij.openapi.util.text.StringUtil;
020 import com.intellij.psi.PsiElement;
021 import kotlin.CollectionsKt;
022 import kotlin.jvm.functions.Function1;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.kotlin.builtins.BuiltinsPackageFragment;
026 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
027 import org.jetbrains.kotlin.builtins.PrimitiveType;
028 import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor;
029 import org.jetbrains.kotlin.codegen.*;
030 import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
031 import org.jetbrains.kotlin.codegen.binding.MutableClosure;
032 import org.jetbrains.kotlin.codegen.binding.PsiCodegenPredictor;
033 import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
034 import org.jetbrains.kotlin.descriptors.*;
035 import org.jetbrains.kotlin.fileClasses.FileClasses;
036 import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
037 import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
038 import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature;
039 import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers;
040 import org.jetbrains.kotlin.load.java.JvmAbi;
041 import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo;
042 import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
043 import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
044 import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageScope;
045 import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider;
046 import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache;
047 import org.jetbrains.kotlin.name.*;
048 import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
049 import org.jetbrains.kotlin.psi.KtExpression;
050 import org.jetbrains.kotlin.psi.KtFile;
051 import org.jetbrains.kotlin.psi.KtFunctionLiteral;
052 import org.jetbrains.kotlin.psi.KtFunctionLiteralExpression;
053 import org.jetbrains.kotlin.resolve.*;
054 import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
055 import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
056 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
057 import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
058 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
059 import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
060 import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
061 import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
062 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
063 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
064 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
065 import org.jetbrains.kotlin.resolve.scopes.AbstractScopeAdapter;
066 import org.jetbrains.kotlin.resolve.scopes.KtScope;
067 import org.jetbrains.kotlin.serialization.deserialization.DeserializedType;
068 import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
069 import org.jetbrains.kotlin.types.*;
070 import org.jetbrains.kotlin.util.OperatorNameConventions;
071 import org.jetbrains.org.objectweb.asm.Type;
072 import org.jetbrains.org.objectweb.asm.commons.Method;
073
074 import java.util.ArrayList;
075 import java.util.List;
076
077 import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isUnit;
078 import static org.jetbrains.kotlin.codegen.AsmUtil.*;
079 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
080 import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
081 import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
082 import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
083 import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
084 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER;
085 import static org.jetbrains.org.objectweb.asm.Opcodes.*;
086
087 public class JetTypeMapper {
088 private final BindingContext bindingContext;
089 private final ClassBuilderMode classBuilderMode;
090 private final JvmFileClassesProvider fileClassesProvider;
091 private final IncrementalCache incrementalCache;
092 private final String moduleName;
093
094 public JetTypeMapper(
095 @NotNull BindingContext bindingContext,
096 @NotNull ClassBuilderMode classBuilderMode,
097 @NotNull JvmFileClassesProvider fileClassesProvider,
098 @Nullable IncrementalCache incrementalCache,
099 @NotNull String moduleName
100 ) {
101 this.bindingContext = bindingContext;
102 this.classBuilderMode = classBuilderMode;
103 this.fileClassesProvider = fileClassesProvider;
104 this.incrementalCache = incrementalCache;
105 this.moduleName = moduleName;
106 }
107
108 @NotNull
109 public BindingContext getBindingContext() {
110 return bindingContext;
111 }
112
113 private enum JetTypeMapperMode {
114 /**
115 * foo.Bar is mapped to Lfoo/Bar;
116 */
117 IMPL,
118 /**
119 * kotlin.Int is mapped to I
120 */
121 VALUE,
122 /**
123 * kotlin.Int is mapped to Ljava/lang/Integer;
124 */
125 TYPE_PARAMETER,
126 /**
127 * kotlin.Int is mapped to Ljava/lang/Integer;
128 * No projections allowed in immediate arguments
129 */
130 SUPER_TYPE,
131 /**
132 * kotlin.reflect.KClass mapped to java.lang.Class
133 * Other types mapped as VALUE
134 */
135 VALUE_FOR_ANNOTATION,
136 /**
137 * kotlin.reflect.KClass mapped to java.lang.Class
138 * Other types mapped as TYPE_PARAMETER
139 */
140 TYPE_PARAMETER_FOR_ANNOTATION;
141
142 boolean isForAnnotation() {
143 return this == VALUE_FOR_ANNOTATION || this == TYPE_PARAMETER_FOR_ANNOTATION;
144 }
145 }
146
147 @NotNull
148 public Type mapOwner(@NotNull DeclarationDescriptor descriptor) {
149 return mapOwner(descriptor, true);
150 }
151
152 public Type mapImplementationOwner(@NotNull DeclarationDescriptor descriptor) {
153 return mapOwner(descriptor, false);
154 }
155
156 @NotNull
157 public Type mapOwner(@NotNull DeclarationDescriptor descriptor, boolean publicFacade) {
158 if (isLocalFunction(descriptor)) {
159 return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
160 }
161
162 DeclarationDescriptor container = descriptor.getContainingDeclaration();
163 if (container instanceof PackageFragmentDescriptor) {
164 String packageMemberOwner = internalNameForPackageMemberOwner((CallableMemberDescriptor) descriptor, publicFacade);
165 return Type.getObjectType(packageMemberOwner);
166 }
167 else if (container instanceof ClassDescriptor) {
168 return mapClass((ClassDescriptor) container);
169 }
170 else if (container instanceof ScriptDescriptor) {
171 return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container);
172 }
173 else {
174 throw new UnsupportedOperationException("Don't know how to map owner for " + descriptor);
175 }
176 }
177
178 @NotNull
179 private String internalNameForPackageMemberOwner(@NotNull CallableMemberDescriptor descriptor, boolean publicFacade) {
180 boolean isAccessor = descriptor instanceof AccessorForCallableDescriptor;
181 if (isAccessor) {
182 descriptor = ((AccessorForCallableDescriptor) descriptor).getCalleeDescriptor();
183 }
184 KtFile file = DescriptorToSourceUtils.getContainingFile(descriptor);
185 if (file != null) {
186 Visibility visibility = descriptor.getVisibility();
187 if (!publicFacade ||
188 descriptor instanceof PropertyDescriptor ||
189 Visibilities.isPrivate(visibility) ||
190 isAccessor/*Cause of KT-9603*/
191 ) {
192 return FileClasses.getFileClassInternalName(fileClassesProvider, file);
193 }
194 else {
195 return FileClasses.getFacadeClassInternalName(fileClassesProvider, file);
196 }
197 }
198
199 CallableMemberDescriptor directMember = getDirectMember(descriptor);
200
201 if (directMember instanceof DeserializedCallableMemberDescriptor) {
202 String facadeFqName = getPackageMemberOwnerInternalName((DeserializedCallableMemberDescriptor) directMember, publicFacade);
203 if (facadeFqName != null) return facadeFqName;
204 }
205
206 throw new RuntimeException("Could not find package member for " + descriptor +
207 " in package fragment " + descriptor.getContainingDeclaration());
208 }
209
210 public static class ContainingClassesInfo {
211 private final ClassId facadeClassId;
212 private final ClassId implClassId;
213
214 public ContainingClassesInfo(ClassId facadeClassId, ClassId implClassId) {
215 this.facadeClassId = facadeClassId;
216 this.implClassId = implClassId;
217 }
218
219 public ClassId getFacadeClassId() {
220 return facadeClassId;
221 }
222
223 public ClassId getImplClassId() {
224 return implClassId;
225 }
226
227 private static @Nullable ContainingClassesInfo forPackageMemberOrNull(
228 @NotNull FqName packageFqName,
229 @Nullable String facadeClassName,
230 @Nullable String implClassName
231 ) {
232 if (facadeClassName == null || implClassName == null) {
233 return null;
234 }
235 return new ContainingClassesInfo(ClassId.topLevel(packageFqName.child(Name.identifier(facadeClassName))),
236 ClassId.topLevel(packageFqName.child(Name.identifier(implClassName))));
237 }
238
239 private static @Nullable ContainingClassesInfo forClassMemberOrNull(@Nullable ClassId classId) {
240 if (classId == null) {
241 return null;
242 }
243 return new ContainingClassesInfo(classId, classId);
244 }
245 }
246
247 public ContainingClassesInfo getContainingClassesForDeserializedCallable(DeserializedCallableMemberDescriptor deserializedDescriptor) {
248 DeclarationDescriptor parentDeclaration = deserializedDescriptor.getContainingDeclaration();
249 ContainingClassesInfo containingClassesInfo;
250 if (parentDeclaration instanceof PackageFragmentDescriptor) {
251 containingClassesInfo = getPackageMemberContainingClassesInfo(deserializedDescriptor);
252 } else {
253 ClassId classId = getContainerClassIdForClassDescriptor((ClassDescriptor) parentDeclaration);
254 containingClassesInfo = ContainingClassesInfo.forClassMemberOrNull(classId);
255 }
256 if (containingClassesInfo == null) {
257 throw new IllegalStateException("Couldn't find container for " + deserializedDescriptor.getName());
258 }
259 return containingClassesInfo;
260 }
261
262 private static ClassId getContainerClassIdForClassDescriptor(ClassDescriptor classDescriptor) {
263 ClassId classId = DescriptorUtilsKt.getClassId(classDescriptor);
264 if (isInterface(classDescriptor)) {
265 FqName relativeClassName = classId.getRelativeClassName();
266 //TODO test nested trait fun inlining
267 classId = new ClassId(classId.getPackageFqName(), Name.identifier(relativeClassName.shortName().asString() + JvmAbi.DEFAULT_IMPLS_SUFFIX));
268 }
269 return classId;
270 }
271
272 @Nullable
273 private String getPackageMemberOwnerInternalName(@NotNull DeserializedCallableMemberDescriptor descriptor, boolean publicFacade) {
274 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
275 assert containingDeclaration instanceof PackageFragmentDescriptor : "Not a top-level member: " + descriptor;
276
277 ContainingClassesInfo containingClasses = getPackageMemberContainingClassesInfo(descriptor);
278 if (containingClasses == null) {
279 return null;
280 }
281
282 ClassId ownerClassId = publicFacade ? containingClasses.getFacadeClassId()
283 : containingClasses.getImplClassId();
284 return JvmClassName.byClassId(ownerClassId).getInternalName();
285 }
286
287 private static final ClassId FAKE_CLASS_ID_FOR_BUILTINS = ClassId.topLevel(new FqName("kotlin.KotlinPackage"));
288
289 @Nullable
290 private ContainingClassesInfo getPackageMemberContainingClassesInfo(@NotNull DeserializedCallableMemberDescriptor descriptor) {
291 // XXX This method is a dirty hack.
292 // We need some safe, concise way to identify multifile facade and multifile part
293 // from a deserialized package member descriptor.
294 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
295 assert containingDeclaration instanceof PackageFragmentDescriptor
296 : "Package member expected, got " + descriptor + " in " + containingDeclaration;
297 PackageFragmentDescriptor packageFragmentDescriptor = (PackageFragmentDescriptor) containingDeclaration;
298
299 if (packageFragmentDescriptor instanceof BuiltinsPackageFragment) {
300 return new ContainingClassesInfo(FAKE_CLASS_ID_FOR_BUILTINS, FAKE_CLASS_ID_FOR_BUILTINS);
301 }
302
303 Name implClassName = JvmFileClassUtil.getImplClassName(descriptor);
304 assert implClassName != null : "No implClassName for " + descriptor;
305 String implSimpleName = implClassName.asString();
306
307 String facadeSimpleName;
308
309 KtScope scope = packageFragmentDescriptor.getMemberScope();
310 if (scope instanceof AbstractScopeAdapter) {
311 scope = ((AbstractScopeAdapter) scope).getActualScope();
312 }
313 if (scope instanceof LazyJavaPackageScope) {
314 facadeSimpleName = ((LazyJavaPackageScope) scope).getFacadeSimpleNameForPartSimpleName(implClassName.asString());
315 }
316 else if (packageFragmentDescriptor instanceof IncrementalPackageFragmentProvider.IncrementalPackageFragment) {
317 assert incrementalCache != null
318 : "IncrementalPackageFragment found outside of incremental compilation context " +
319 "for " + descriptor + " in package " + packageFragmentDescriptor;
320
321 String implClassInternalName = internalNameByFqNameWithoutInnerClasses(
322 packageFragmentDescriptor.getFqName().child(implClassName));
323 String facadeClassInternalName = incrementalCache.getMultifileFacade(implClassInternalName);
324 if (facadeClassInternalName == null) {
325 facadeSimpleName = implClassName.asString();
326 }
327 else {
328 facadeSimpleName = getSimpleInternalName(facadeClassInternalName);
329 }
330 }
331 else {
332 throw new AssertionError("Unexpected package member scope for " + descriptor + ": " +
333 scope + " :" + scope.getClass().getSimpleName());
334 }
335 return ContainingClassesInfo.forPackageMemberOrNull(packageFragmentDescriptor.getFqName(), facadeSimpleName, implSimpleName);
336 }
337
338 @NotNull
339 public Type mapReturnType(@NotNull CallableDescriptor descriptor) {
340 return mapReturnType(descriptor, null);
341 }
342
343 @NotNull
344 private Type mapReturnType(@NotNull CallableDescriptor descriptor, @Nullable BothSignatureWriter sw) {
345 KotlinType returnType = descriptor.getReturnType();
346 assert returnType != null : "Function has no return type: " + descriptor;
347
348 if (descriptor instanceof ConstructorDescriptor) {
349 return Type.VOID_TYPE;
350 }
351
352 if (isUnit(returnType) && !TypeUtils.isNullableType(returnType) && !(descriptor instanceof PropertyGetterDescriptor)) {
353 if (sw != null) {
354 sw.writeAsmType(Type.VOID_TYPE);
355 }
356 return Type.VOID_TYPE;
357 }
358 else if (descriptor instanceof FunctionDescriptor && forceBoxedReturnType((FunctionDescriptor) descriptor)) {
359 // TYPE_PARAMETER is a hack to automatically box the return type
360 //noinspection ConstantConditions
361 return mapType(descriptor.getReturnType(), sw, JetTypeMapperMode.TYPE_PARAMETER);
362 }
363 else if (DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration())) {
364 //noinspection ConstantConditions
365 return mapType(descriptor.getReturnType(), sw, JetTypeMapperMode.VALUE_FOR_ANNOTATION);
366 }
367 else {
368 return mapType(returnType, sw, JetTypeMapperMode.VALUE, Variance.OUT_VARIANCE);
369 }
370 }
371
372 @NotNull
373 private Type mapType(@NotNull KotlinType jetType, @NotNull JetTypeMapperMode mode) {
374 return mapType(jetType, null, mode);
375 }
376
377 @NotNull
378 public Type mapSupertype(@NotNull KotlinType jetType, @Nullable BothSignatureWriter signatureVisitor) {
379 return mapType(jetType, signatureVisitor, JetTypeMapperMode.SUPER_TYPE);
380 }
381
382 @NotNull
383 public Type mapTypeParameter(@NotNull KotlinType jetType, @Nullable BothSignatureWriter signatureVisitor) {
384 return mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
385 }
386
387 @NotNull
388 public Type mapClass(@NotNull ClassifierDescriptor classifier) {
389 return mapType(classifier.getDefaultType(), null, JetTypeMapperMode.IMPL);
390 }
391
392 @NotNull
393 public Type mapType(@NotNull KotlinType jetType) {
394 return mapType(jetType, null, JetTypeMapperMode.VALUE);
395 }
396
397 @NotNull
398 public Type mapType(@NotNull CallableDescriptor descriptor) {
399 //noinspection ConstantConditions
400 return mapType(descriptor.getReturnType());
401 }
402
403 @NotNull
404 public JvmMethodSignature mapAnnotationParameterSignature(@NotNull PropertyDescriptor descriptor) {
405 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
406 sw.writeReturnType();
407 mapType(descriptor.getType(), sw, JetTypeMapperMode.VALUE_FOR_ANNOTATION);
408 sw.writeReturnTypeEnd();
409 return sw.makeJvmMethodSignature(descriptor.getName().asString());
410 }
411
412 @NotNull
413 public Type mapType(@NotNull ClassifierDescriptor descriptor) {
414 return mapType(descriptor.getDefaultType());
415 }
416
417 @NotNull
418 private Type mapType(@NotNull KotlinType jetType, @Nullable BothSignatureWriter signatureVisitor, @NotNull JetTypeMapperMode mode) {
419 return mapType(jetType, signatureVisitor, mode, Variance.INVARIANT);
420 }
421
422 @NotNull
423 private Type mapType(
424 @NotNull KotlinType jetType,
425 @Nullable BothSignatureWriter signatureVisitor,
426 @NotNull JetTypeMapperMode kind,
427 @NotNull Variance howThisTypeIsUsed
428 ) {
429 Type known = mapBuiltinType(jetType);
430
431 boolean projectionsAllowed = kind != JetTypeMapperMode.SUPER_TYPE;
432 if (known != null) {
433 if (kind == JetTypeMapperMode.VALUE || kind == JetTypeMapperMode.VALUE_FOR_ANNOTATION) {
434 return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
435 }
436 else if (kind == JetTypeMapperMode.TYPE_PARAMETER || kind == JetTypeMapperMode.SUPER_TYPE ||
437 kind == JetTypeMapperMode.TYPE_PARAMETER_FOR_ANNOTATION) {
438 return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed, projectionsAllowed);
439 }
440 else if (kind == JetTypeMapperMode.IMPL) {
441 // TODO: enable and fix tests
442 //throw new IllegalStateException("must not map known type to IMPL when not compiling builtins: " + jetType);
443 return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
444 }
445 else {
446 throw new IllegalStateException("unknown kind: " + kind);
447 }
448 }
449
450 TypeConstructor constructor = jetType.getConstructor();
451 DeclarationDescriptor descriptor = constructor.getDeclarationDescriptor();
452 if (constructor instanceof IntersectionTypeConstructor) {
453 jetType = CommonSupertypes.commonSupertype(new ArrayList<KotlinType>(constructor.getSupertypes()));
454 }
455
456 if (descriptor == null) {
457 throw new UnsupportedOperationException("no descriptor for type constructor of " + jetType);
458 }
459
460 if (ErrorUtils.isError(descriptor)) {
461 if (classBuilderMode != ClassBuilderMode.LIGHT_CLASSES) {
462 throw new IllegalStateException(generateErrorMessageForErrorType(jetType, descriptor));
463 }
464 Type asmType = Type.getObjectType("error/NonExistentClass");
465 if (signatureVisitor != null) {
466 signatureVisitor.writeAsmType(asmType);
467 }
468 return asmType;
469 }
470
471 if (descriptor instanceof ClassDescriptor && KotlinBuiltIns.isArray(jetType)) {
472 if (jetType.getArguments().size() != 1) {
473 throw new UnsupportedOperationException("arrays must have one type argument");
474 }
475 TypeProjection memberProjection = jetType.getArguments().get(0);
476 KotlinType memberType = memberProjection.getType();
477
478 Type arrayElementType;
479 if (memberProjection.getProjectionKind() == Variance.IN_VARIANCE) {
480 arrayElementType = AsmTypes.OBJECT_TYPE;
481 if (signatureVisitor != null) {
482 signatureVisitor.writeArrayType();
483 signatureVisitor.writeAsmType(arrayElementType);
484 signatureVisitor.writeArrayEnd();
485 }
486 }
487 else {
488 arrayElementType = boxType(mapType(memberType, kind));
489 if (signatureVisitor != null) {
490 signatureVisitor.writeArrayType();
491 JetTypeMapperMode newMode = kind.isForAnnotation() ?
492 JetTypeMapperMode.TYPE_PARAMETER_FOR_ANNOTATION :
493 JetTypeMapperMode.TYPE_PARAMETER;
494 mapType(memberType, signatureVisitor, newMode, memberProjection.getProjectionKind());
495 signatureVisitor.writeArrayEnd();
496 }
497 }
498
499 return Type.getType("[" + arrayElementType.getDescriptor());
500 }
501
502 if (descriptor instanceof ClassDescriptor) {
503 Type asmType = kind.isForAnnotation() && KotlinBuiltIns.isKClass((ClassDescriptor) descriptor) ?
504 AsmTypes.JAVA_CLASS_TYPE :
505 computeAsmType((ClassDescriptor) descriptor.getOriginal());
506 writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, projectionsAllowed);
507 return asmType;
508 }
509
510 if (descriptor instanceof TypeParameterDescriptor) {
511 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
512 Type type = mapType(typeParameterDescriptor.getUpperBounds().iterator().next(), kind);
513 if (signatureVisitor != null) {
514 signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), type);
515 }
516 return type;
517 }
518
519 throw new UnsupportedOperationException("Unknown type " + jetType);
520 }
521
522 @Nullable
523 private static Type mapBuiltinType(@NotNull KotlinType type) {
524 DeclarationDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
525 if (!(descriptor instanceof ClassDescriptor)) return null;
526
527 FqNameUnsafe fqName = DescriptorUtils.getFqName(descriptor);
528
529 PrimitiveType primitiveType = KotlinBuiltIns.getPrimitiveTypeByFqName(fqName);
530 if (primitiveType != null) {
531 Type asmType = Type.getType(JvmPrimitiveType.get(primitiveType).getDesc());
532 return TypeUtils.isNullableType(type) ? boxType(asmType) : asmType;
533 }
534
535 PrimitiveType arrayElementType = KotlinBuiltIns.getPrimitiveTypeByArrayClassFqName(fqName);
536 if (arrayElementType != null) {
537 return Type.getType("[" + JvmPrimitiveType.get(arrayElementType).getDesc());
538 }
539
540 ClassId classId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqName);
541 if (classId != null) {
542 return Type.getObjectType(JvmClassName.byClassId(classId).getInternalName());
543 }
544
545 return null;
546 }
547
548 @NotNull
549 private Type computeAsmType(@NotNull ClassDescriptor klass) {
550 Type alreadyComputedType = bindingContext.get(ASM_TYPE, klass);
551 if (alreadyComputedType != null) {
552 return alreadyComputedType;
553 }
554
555 Type asmType = Type.getObjectType(computeAsmTypeImpl(klass));
556 assert PsiCodegenPredictor.checkPredictedNameFromPsi(klass, asmType, fileClassesProvider);
557 return asmType;
558 }
559
560 @NotNull
561 private String computeAsmTypeImpl(@NotNull ClassDescriptor klass) {
562 DeclarationDescriptor container = klass.getContainingDeclaration();
563
564 String name = SpecialNames.safeIdentifier(klass.getName()).getIdentifier();
565 if (container instanceof PackageFragmentDescriptor) {
566 FqName fqName = ((PackageFragmentDescriptor) container).getFqName();
567 return fqName.isRoot() ? name : fqName.asString().replace('.', '/') + '/' + name;
568 }
569
570 if (container instanceof ScriptDescriptor) {
571 return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container).getInternalName() + "$" + name;
572 }
573
574 assert container instanceof ClassDescriptor : "Unexpected container: " + container + " for " + klass;
575
576 String containerInternalName = computeAsmTypeImpl((ClassDescriptor) container);
577 return klass.getKind() == ClassKind.ENUM_ENTRY ? containerInternalName : containerInternalName + "$" + name;
578 }
579
580 @NotNull
581 public Type mapDefaultImpls(@NotNull ClassDescriptor descriptor) {
582 return Type.getObjectType(mapType(descriptor).getInternalName() + JvmAbi.DEFAULT_IMPLS_SUFFIX);
583 }
584
585 @NotNull
586 private static String generateErrorMessageForErrorType(@NotNull KotlinType type, @NotNull DeclarationDescriptor descriptor) {
587 PsiElement declarationElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
588
589 if (declarationElement == null) {
590 String message = "Error type encountered: %s (%s).";
591 if (FlexibleTypesKt.upperIfFlexible(type) instanceof DeserializedType) {
592 message +=
593 " One of the possible reasons may be that this type is not directly accessible from this module. " +
594 "To workaround this error, try adding an explicit dependency on the module or library which contains this type " +
595 "to the classpath";
596 }
597 return String.format(message, type, type.getClass().getSimpleName());
598 }
599
600 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
601 PsiElement parentDeclarationElement =
602 containingDeclaration != null ? DescriptorToSourceUtils.descriptorToDeclaration(containingDeclaration) : null;
603
604 return String.format(
605 "Error type encountered: %s (%s). Descriptor: %s. For declaration %s:%s in %s:%s",
606 type,
607 type.getClass().getSimpleName(),
608 descriptor,
609 declarationElement,
610 declarationElement.getText(),
611 parentDeclarationElement,
612 parentDeclarationElement != null ? parentDeclarationElement.getText() : "null"
613 );
614 }
615
616 private void writeGenericType(
617 BothSignatureWriter signatureVisitor,
618 Type asmType,
619 KotlinType jetType,
620 Variance howThisTypeIsUsed,
621 boolean projectionsAllowed
622 ) {
623 if (signatureVisitor != null) {
624 if (hasNothingInArguments(jetType)) {
625 signatureVisitor.writeAsmType(asmType);
626 return;
627 }
628
629 signatureVisitor.writeClassBegin(asmType);
630
631 List<TypeProjection> arguments = jetType.getArguments();
632 for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) {
633 TypeProjection argument = arguments.get(parameter.getIndex());
634
635 if (projectionsAllowed && argument.isStarProjection()) {
636 signatureVisitor.writeUnboundedWildcard();
637 }
638 else {
639 Variance projectionKind = projectionsAllowed
640 ? getEffectiveVariance(
641 parameter.getVariance(),
642 argument.getProjectionKind(),
643 howThisTypeIsUsed
644 )
645 : Variance.INVARIANT;
646 signatureVisitor.writeTypeArgument(projectionKind);
647
648 mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
649 signatureVisitor.writeTypeArgumentEnd();
650 }
651 }
652 signatureVisitor.writeClassEnd();
653 }
654 }
655
656 private static boolean hasNothingInArguments(KotlinType jetType) {
657 boolean hasNothingInArguments = CollectionsKt.any(jetType.getArguments(), new Function1<TypeProjection, Boolean>() {
658 @Override
659 public Boolean invoke(TypeProjection projection) {
660 return KotlinBuiltIns.isNothingOrNullableNothing(projection.getType());
661 }
662 });
663
664 if (hasNothingInArguments) return true;
665
666 return CollectionsKt.any(jetType.getArguments(), new Function1<TypeProjection, Boolean>() {
667 @Override
668 public Boolean invoke(TypeProjection projection) {
669 return !projection.isStarProjection() && hasNothingInArguments(projection.getType());
670 }
671 });
672 }
673
674 private static Variance getEffectiveVariance(Variance parameterVariance, Variance projectionKind, Variance howThisTypeIsUsed) {
675 // Return type must not contain wildcards
676 if (howThisTypeIsUsed == Variance.OUT_VARIANCE) return projectionKind;
677
678 if (parameterVariance == Variance.INVARIANT) {
679 return projectionKind;
680 }
681 if (projectionKind == Variance.INVARIANT) {
682 return parameterVariance;
683 }
684 if (parameterVariance == projectionKind) {
685 return parameterVariance;
686 }
687
688 // In<out X> = In<*>
689 // Out<in X> = Out<*>
690 return Variance.OUT_VARIANCE;
691 }
692
693 private Type mapKnownAsmType(
694 KotlinType jetType,
695 Type asmType,
696 @Nullable BothSignatureWriter signatureVisitor,
697 @NotNull Variance howThisTypeIsUsed
698 ) {
699 return mapKnownAsmType(jetType, asmType, signatureVisitor, howThisTypeIsUsed, true);
700 }
701
702 private Type mapKnownAsmType(
703 KotlinType jetType,
704 Type asmType,
705 @Nullable BothSignatureWriter signatureVisitor,
706 @NotNull Variance howThisTypeIsUsed,
707 boolean allowProjections
708 ) {
709 if (signatureVisitor != null) {
710 if (jetType.getArguments().isEmpty()) {
711 signatureVisitor.writeAsmType(asmType);
712 }
713 else {
714 writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, allowProjections);
715 }
716 }
717 return asmType;
718 }
719
720 @NotNull
721 public CallableMethod mapToCallableMethod(@NotNull FunctionDescriptor descriptor, boolean superCall) {
722 if (descriptor instanceof ConstructorDescriptor) {
723 JvmMethodSignature method = mapSignature(descriptor);
724 Type owner = mapClass(((ConstructorDescriptor) descriptor).getContainingDeclaration());
725 return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL, null, null, null);
726 }
727
728 DeclarationDescriptor functionParent = descriptor.getOriginal().getContainingDeclaration();
729
730 FunctionDescriptor functionDescriptor = unwrapFakeOverride(descriptor.getOriginal());
731
732 JvmMethodSignature signature;
733 Type owner;
734 Type ownerForDefaultImpl;
735 Type ownerForDefaultParam;
736 int invokeOpcode;
737 Type thisClass;
738
739 if (functionParent instanceof ClassDescriptor) {
740 FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor);
741
742 ClassDescriptor currentOwner = (ClassDescriptor) functionParent;
743 ClassDescriptor declarationOwner = (ClassDescriptor) declarationFunctionDescriptor.getContainingDeclaration();
744
745 boolean originalIsInterface = isJvmInterface(declarationOwner);
746 boolean currentIsInterface = isJvmInterface(currentOwner);
747
748 boolean isInterface = currentIsInterface && originalIsInterface;
749
750 ClassDescriptor ownerForDefault = (ClassDescriptor) findBaseDeclaration(functionDescriptor).getContainingDeclaration();
751 ownerForDefaultParam = mapClass(ownerForDefault);
752 ownerForDefaultImpl = isJvmInterface(ownerForDefault) ? mapDefaultImpls(ownerForDefault) : ownerForDefaultParam;
753
754 if (isInterface && (superCall || descriptor.getVisibility() == Visibilities.PRIVATE)) {
755 thisClass = mapClass(currentOwner);
756 if (declarationOwner instanceof JavaClassDescriptor) {
757 invokeOpcode = INVOKESPECIAL;
758 signature = mapSignature(functionDescriptor);
759 owner = thisClass;
760 }
761 else {
762 invokeOpcode = INVOKESTATIC;
763 signature = mapSignature(descriptor.getOriginal(), OwnerKind.DEFAULT_IMPLS);
764 owner = mapDefaultImpls(currentOwner);
765 }
766 }
767 else {
768 boolean isStaticInvocation = (isStaticDeclaration(functionDescriptor) &&
769 !(functionDescriptor instanceof ImportedFromObjectCallableDescriptor)) ||
770 isStaticAccessor(functionDescriptor) ||
771 AnnotationUtilKt.isPlatformStaticInObjectOrClass(functionDescriptor);
772 if (isStaticInvocation) {
773 invokeOpcode = INVOKESTATIC;
774 }
775 else if (isInterface) {
776 invokeOpcode = INVOKEINTERFACE;
777 }
778 else {
779 boolean isPrivateFunInvocation = Visibilities.isPrivate(functionDescriptor.getVisibility());
780 invokeOpcode = superCall || isPrivateFunInvocation ? INVOKESPECIAL : INVOKEVIRTUAL;
781 }
782
783 FunctionDescriptor overriddenSpecialBuiltinFunction =
784 SpecialBuiltinMembers.<FunctionDescriptor>getOverriddenBuiltinWithDifferentJvmDescriptor(functionDescriptor.getOriginal());
785 FunctionDescriptor functionToCall = overriddenSpecialBuiltinFunction != null
786 ? overriddenSpecialBuiltinFunction.getOriginal()
787 : functionDescriptor.getOriginal();
788
789 signature = mapSignature(functionToCall);
790
791 ClassDescriptor receiver = (currentIsInterface && !originalIsInterface) || currentOwner instanceof FunctionClassDescriptor
792 ? declarationOwner
793 : currentOwner;
794 owner = mapClass(receiver);
795 thisClass = owner;
796 }
797 }
798 else {
799 signature = mapSignature(functionDescriptor.getOriginal());
800 owner = mapOwner(functionDescriptor);
801 ownerForDefaultParam = owner;
802 ownerForDefaultImpl = owner;
803 if (functionParent instanceof PackageFragmentDescriptor) {
804 invokeOpcode = INVOKESTATIC;
805 thisClass = null;
806 }
807 else if (functionDescriptor instanceof ConstructorDescriptor) {
808 invokeOpcode = INVOKESPECIAL;
809 thisClass = null;
810 }
811 else {
812 invokeOpcode = INVOKEVIRTUAL;
813 thisClass = owner;
814 }
815 }
816
817 Type calleeType = isLocalFunction(functionDescriptor) ? owner : null;
818
819 Type receiverParameterType;
820 ReceiverParameterDescriptor receiverParameter = functionDescriptor.getOriginal().getExtensionReceiverParameter();
821 if (receiverParameter != null) {
822 receiverParameterType = mapType(receiverParameter.getType());
823 }
824 else {
825 receiverParameterType = null;
826 }
827 return new CallableMethod(
828 owner, ownerForDefaultImpl, ownerForDefaultParam, signature, invokeOpcode,
829 thisClass, receiverParameterType, calleeType);
830 }
831
832 public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
833 return descriptor instanceof AccessorForCallableDescriptor<?>;
834 }
835
836 public static boolean isStaticAccessor(@NotNull CallableMemberDescriptor descriptor) {
837 if (descriptor instanceof AccessorForConstructorDescriptor) return false;
838 return isAccessor(descriptor);
839 }
840
841 @NotNull
842 private static FunctionDescriptor findAnyDeclaration(@NotNull FunctionDescriptor function) {
843 if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
844 return function;
845 }
846 return findBaseDeclaration(function);
847 }
848
849 @NotNull
850 private static FunctionDescriptor findBaseDeclaration(@NotNull FunctionDescriptor function) {
851 if (function.getOverriddenDescriptors().isEmpty()) {
852 return function;
853 }
854 else {
855 // TODO: prefer class to interface
856 return findBaseDeclaration(function.getOverriddenDescriptors().iterator().next());
857 }
858 }
859
860 @NotNull
861 private String mapFunctionName(@NotNull FunctionDescriptor descriptor) {
862 if (!(descriptor instanceof JavaCallableMemberDescriptor)) {
863 String platformName = getJvmName(descriptor);
864 if (platformName != null) return platformName;
865 }
866
867 String nameForSpecialFunction = SpecialBuiltinMembers.getJvmMethodNameIfSpecial(descriptor);
868 if (nameForSpecialFunction != null) return nameForSpecialFunction;
869
870 if (descriptor instanceof PropertyAccessorDescriptor) {
871 PropertyDescriptor property = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty();
872 if (isAnnotationClass(property.getContainingDeclaration())) {
873 return property.getName().asString();
874 }
875
876 boolean isAccessor = property instanceof AccessorForPropertyDescriptor;
877 String propertyName = isAccessor
878 ? ((AccessorForPropertyDescriptor) property).getAccessorSuffix()
879 : property.getName().asString();
880
881 String accessorName = descriptor instanceof PropertyGetterDescriptor
882 ? JvmAbi.getterName(propertyName)
883 : JvmAbi.setterName(propertyName);
884
885 return updateMemberNameIfInternal(isAccessor ? "access$" + accessorName : accessorName, descriptor);
886 }
887 else if (isFunctionLiteral(descriptor)) {
888 PsiElement element = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor);
889 if (element instanceof KtFunctionLiteral) {
890 PsiElement expression = element.getParent();
891 if (expression instanceof KtFunctionLiteralExpression) {
892 SamType samType = bindingContext.get(SAM_VALUE, (KtExpression) expression);
893 if (samType != null) {
894 return samType.getAbstractMethod().getName().asString();
895 }
896 }
897 }
898
899 return OperatorNameConventions.INVOKE.asString();
900 }
901 else if (isLocalFunction(descriptor) || isFunctionExpression(descriptor)) {
902 return OperatorNameConventions.INVOKE.asString();
903 }
904 else {
905 return updateMemberNameIfInternal(descriptor.getName().asString(), descriptor);
906 }
907 }
908
909 @NotNull
910 public static String mapDefaultFieldName(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegated) {
911 String name;
912 if (propertyDescriptor instanceof AccessorForPropertyDescriptor) {
913 name = ((AccessorForPropertyDescriptor) propertyDescriptor).getCalleeDescriptor().getName().asString();
914 }
915 else {
916 name = propertyDescriptor.getName().asString();
917 }
918 return isDelegated ? name + JvmAbi.DELEGATED_PROPERTY_NAME_SUFFIX : name;
919 }
920
921 @NotNull
922 private String updateMemberNameIfInternal(@NotNull String name, @NotNull CallableMemberDescriptor descriptor) {
923 if (descriptor.getContainingDeclaration() instanceof ScriptDescriptor) {
924 //script properties should be public
925 return name;
926 }
927
928 if (DescriptorUtils.isTopLevelDeclaration(descriptor)) {
929 return name;
930 }
931
932 if (!(descriptor instanceof ConstructorDescriptor) && descriptor.getVisibility() == Visibilities.INTERNAL) {
933 return name + "$" + JvmAbi.sanitizeAsJavaIdentifier(moduleName);
934 }
935
936 return name;
937 }
938
939 @NotNull
940 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor descriptor) {
941 return mapSignature(descriptor, OwnerKind.IMPLEMENTATION);
942 }
943
944 @NotNull
945 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind) {
946 if (f instanceof ConstructorDescriptor) {
947 return mapSignature(f, kind, f.getOriginal().getValueParameters());
948 }
949 return mapSignature(f, kind, f.getValueParameters());
950 }
951
952 @NotNull
953 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind,
954 List<ValueParameterDescriptor> valueParameters) {
955 if (f instanceof FunctionImportedFromObject) {
956 return mapSignature(((FunctionImportedFromObject) f).getFunctionFromObject());
957 }
958
959 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
960
961 if (f instanceof ConstructorDescriptor) {
962 sw.writeParametersStart();
963 writeAdditionalConstructorParameters((ConstructorDescriptor) f, sw);
964
965 for (ValueParameterDescriptor parameter : valueParameters) {
966 writeParameter(sw, parameter.getType());
967 }
968
969 if (f instanceof AccessorForConstructorDescriptor) {
970 writeParameter(sw, JvmMethodParameterKind.CONSTRUCTOR_MARKER, DEFAULT_CONSTRUCTOR_MARKER);
971 }
972
973 writeVoidReturn(sw);
974 }
975 else {
976 writeFormalTypeParameters(getDirectMember(f).getTypeParameters(), sw);
977
978 sw.writeParametersStart();
979 writeThisIfNeeded(f, kind, sw);
980
981 ReceiverParameterDescriptor receiverParameter = f.getExtensionReceiverParameter();
982 if (receiverParameter != null) {
983 writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.getType());
984 }
985
986 for (ValueParameterDescriptor parameter : valueParameters) {
987 if (writeCustomParameter(f, parameter, sw)) continue;
988 writeParameter(sw, parameter.getType());
989 }
990
991 sw.writeReturnType();
992 mapReturnType(f, sw);
993 sw.writeReturnTypeEnd();
994 }
995
996 JvmMethodSignature signature = sw.makeJvmMethodSignature(mapFunctionName(f));
997
998
999 if (kind != OwnerKind.DEFAULT_IMPLS) {
1000 SpecialSignatureInfo specialSignatureInfo = BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo(f);
1001
1002 if (specialSignatureInfo != null) {
1003 return new JvmMethodSignature(
1004 signature.getAsmMethod(), specialSignatureInfo.getSignature(), signature.getValueParameters());
1005 }
1006 }
1007
1008 return signature;
1009 }
1010
1011 private boolean writeCustomParameter(
1012 @NotNull FunctionDescriptor f,
1013 @NotNull ValueParameterDescriptor parameter,
1014 @NotNull BothSignatureWriter sw
1015 ) {
1016 FunctionDescriptor overridden =
1017 BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(f);
1018 if (overridden == null) return false;
1019 if (SpecialBuiltinMembers.isFromJavaOrBuiltins(f)) return false;
1020
1021 if (overridden.getName().asString().equals("remove") && mapType(parameter.getType()).getSort() == Type.INT) {
1022 writeParameter(sw, TypeUtils.makeNullable(parameter.getType()));
1023 return true;
1024 }
1025
1026 return false;
1027 }
1028
1029 @NotNull
1030 public static String getDefaultDescriptor(@NotNull Method method, @Nullable String dispatchReceiverDescriptor, boolean isExtension) {
1031 String descriptor = method.getDescriptor();
1032 int argumentsCount = Type.getArgumentTypes(descriptor).length;
1033 if (isExtension) {
1034 argumentsCount--;
1035 }
1036 int maskArgumentsCount = (argumentsCount + Integer.SIZE - 1) / Integer.SIZE;
1037 String additionalArgs = StringUtil.repeat(Type.INT_TYPE.getDescriptor(), maskArgumentsCount);
1038 if (isConstructor(method)) {
1039 additionalArgs += DEFAULT_CONSTRUCTOR_MARKER.getDescriptor();
1040 }
1041 String result = descriptor.replace(")", additionalArgs + ")");
1042 if (dispatchReceiverDescriptor != null && !isConstructor(method)) {
1043 return result.replace("(", "(" + dispatchReceiverDescriptor);
1044 }
1045 return result;
1046 }
1047
1048 public ClassBuilderMode getClassBuilderMode() {
1049 return classBuilderMode;
1050 }
1051
1052 private static boolean isConstructor(@NotNull Method method) {
1053 return "<init>".equals(method.getName());
1054 }
1055
1056 @NotNull
1057 public Method mapDefaultMethod(@NotNull FunctionDescriptor functionDescriptor, @NotNull OwnerKind kind) {
1058 Method jvmSignature = mapSignature(functionDescriptor, kind).getAsmMethod();
1059 Type ownerType = mapOwner(functionDescriptor);
1060 boolean isConstructor = isConstructor(jvmSignature);
1061 String descriptor = getDefaultDescriptor(
1062 jvmSignature,
1063 isStaticMethod(kind, functionDescriptor) || isConstructor ? null : ownerType.getDescriptor(),
1064 functionDescriptor.getExtensionReceiverParameter() != null
1065 );
1066
1067 return new Method(isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, descriptor);
1068 }
1069
1070 /**
1071 * @return true iff a given function descriptor should be compiled to a method with boxed return type regardless of whether return type
1072 * of that descriptor is nullable or not. This happens when a function returning a value of a primitive type overrides another function
1073 * with a non-primitive return type. In that case the generated method's return type should be boxed: otherwise it's not possible to use
1074 * this class from Java since javac issues errors when loading the class (incompatible return types)
1075 */
1076 private static boolean forceBoxedReturnType(@NotNull FunctionDescriptor descriptor) {
1077 //noinspection ConstantConditions
1078 if (!KotlinBuiltIns.isPrimitiveType(descriptor.getReturnType())) return false;
1079
1080 for (FunctionDescriptor overridden : getAllOverriddenDescriptors(descriptor)) {
1081 //noinspection ConstantConditions
1082 if (!KotlinBuiltIns.isPrimitiveType(overridden.getOriginal().getReturnType())) return true;
1083 }
1084
1085 return false;
1086 }
1087
1088 private static void writeVoidReturn(@NotNull BothSignatureWriter sw) {
1089 sw.writeReturnType();
1090 sw.writeAsmType(Type.VOID_TYPE);
1091 sw.writeReturnTypeEnd();
1092 }
1093
1094 @Nullable
1095 public String mapFieldSignature(@NotNull KotlinType backingFieldType) {
1096 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
1097 mapType(backingFieldType, sw, JetTypeMapperMode.VALUE);
1098 return sw.makeJavaGenericSignature();
1099 }
1100
1101 private void writeThisIfNeeded(
1102 @NotNull CallableMemberDescriptor descriptor,
1103 @NotNull OwnerKind kind,
1104 @NotNull BothSignatureWriter sw
1105 ) {
1106 ClassDescriptor thisType;
1107 if (kind == OwnerKind.DEFAULT_IMPLS) {
1108 thisType = getTraitImplThisParameterClass((ClassDescriptor) descriptor.getContainingDeclaration());
1109 }
1110 else if (isAccessor(descriptor) && descriptor.getDispatchReceiverParameter() != null) {
1111 thisType = (ClassDescriptor) descriptor.getContainingDeclaration();
1112 }
1113 else return;
1114
1115 writeParameter(sw, JvmMethodParameterKind.THIS, thisType.getDefaultType());
1116 }
1117
1118 @NotNull
1119 private static ClassDescriptor getTraitImplThisParameterClass(@NotNull ClassDescriptor traitDescriptor) {
1120 for (ClassDescriptor descriptor : DescriptorUtils.getSuperclassDescriptors(traitDescriptor)) {
1121 if (descriptor.getKind() != ClassKind.INTERFACE) {
1122 return descriptor;
1123 }
1124 }
1125 return traitDescriptor;
1126 }
1127
1128 public void writeFormalTypeParameters(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull BothSignatureWriter sw) {
1129 for (TypeParameterDescriptor typeParameter : typeParameters) {
1130 writeFormalTypeParameter(typeParameter, sw);
1131 }
1132 }
1133
1134 private void writeFormalTypeParameter(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull BothSignatureWriter sw) {
1135 if (classBuilderMode == ClassBuilderMode.LIGHT_CLASSES && typeParameterDescriptor.getName().isSpecial()) {
1136 // If a type parameter has no name, the code below fails, but it should recover in case of light classes
1137 return;
1138 }
1139
1140 sw.writeFormalTypeParameter(typeParameterDescriptor.getName().asString());
1141
1142 classBound:
1143 {
1144 sw.writeClassBound();
1145
1146 for (KotlinType jetType : typeParameterDescriptor.getUpperBounds()) {
1147 if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
1148 if (!isJvmInterface(jetType)) {
1149 mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
1150 break classBound;
1151 }
1152 }
1153 }
1154
1155 // "extends Object" is optional according to ClassFileFormat-Java5.pdf
1156 // but javac complaints to signature:
1157 // <P:>Ljava/lang/Object;
1158 // TODO: avoid writing java/lang/Object if interface list is not empty
1159 }
1160 sw.writeClassBoundEnd();
1161
1162 for (KotlinType jetType : typeParameterDescriptor.getUpperBounds()) {
1163 ClassifierDescriptor classifier = jetType.getConstructor().getDeclarationDescriptor();
1164 if (classifier instanceof ClassDescriptor) {
1165 if (isJvmInterface(jetType)) {
1166 sw.writeInterfaceBound();
1167 mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
1168 sw.writeInterfaceBoundEnd();
1169 }
1170 }
1171 else if (classifier instanceof TypeParameterDescriptor) {
1172 sw.writeInterfaceBound();
1173 mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
1174 sw.writeInterfaceBoundEnd();
1175 }
1176 else {
1177 throw new UnsupportedOperationException("Unknown classifier: " + classifier);
1178 }
1179 }
1180 }
1181
1182 private void writeParameter(@NotNull BothSignatureWriter sw, @NotNull KotlinType type) {
1183 writeParameter(sw, JvmMethodParameterKind.VALUE, type);
1184 }
1185
1186 private void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JvmMethodParameterKind kind, @NotNull KotlinType type) {
1187 sw.writeParameterType(kind);
1188 mapType(type, sw, JetTypeMapperMode.VALUE);
1189 sw.writeParameterTypeEnd();
1190 }
1191
1192 private static void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JvmMethodParameterKind kind, @NotNull Type type) {
1193 sw.writeParameterType(kind);
1194 sw.writeAsmType(type);
1195 sw.writeParameterTypeEnd();
1196 }
1197
1198 private void writeAdditionalConstructorParameters(@NotNull ConstructorDescriptor descriptor, @NotNull BothSignatureWriter sw) {
1199 MutableClosure closure = bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration());
1200
1201 ClassDescriptor captureThis = getDispatchReceiverParameterForConstructorCall(descriptor, closure);
1202 if (captureThis != null) {
1203 writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType());
1204 }
1205
1206 KotlinType captureReceiverType = closure != null ? closure.getCaptureReceiverType() : null;
1207 if (captureReceiverType != null) {
1208 writeParameter(sw, JvmMethodParameterKind.RECEIVER, captureReceiverType);
1209 }
1210
1211 ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
1212 if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
1213 writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getStringType());
1214 writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getIntType());
1215 }
1216
1217 if (closure == null) return;
1218
1219 for (DeclarationDescriptor variableDescriptor : closure.getCaptureVariables().keySet()) {
1220 Type type;
1221 if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) {
1222 Type sharedVarType = getSharedVarType(variableDescriptor);
1223 if (sharedVarType == null) {
1224 sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType());
1225 }
1226 type = sharedVarType;
1227 }
1228 else if (isLocalFunction(variableDescriptor)) {
1229 //noinspection CastConflictsWithInstanceof
1230 type = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) variableDescriptor);
1231 }
1232 else {
1233 type = null;
1234 }
1235
1236 if (type != null) {
1237 closure.setCapturedParameterOffsetInConstructor(variableDescriptor, sw.getCurrentSignatureSize() + 1);
1238 writeParameter(sw, JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE, type);
1239 }
1240 }
1241
1242 // We may generate a slightly wrong signature for a local class / anonymous object in light classes mode but we don't care,
1243 // because such classes are not accessible from the outside world
1244 if (classBuilderMode == ClassBuilderMode.FULL) {
1245 ResolvedCall<ConstructorDescriptor> superCall = findFirstDelegatingSuperCall(descriptor);
1246 if (superCall == null) return;
1247 writeSuperConstructorCallParameters(sw, descriptor, superCall, captureThis != null);
1248 }
1249 }
1250
1251 private void writeSuperConstructorCallParameters(
1252 @NotNull BothSignatureWriter sw,
1253 @NotNull ConstructorDescriptor descriptor,
1254 @NotNull ResolvedCall<ConstructorDescriptor> superCall,
1255 boolean hasOuter
1256 ) {
1257 ConstructorDescriptor superDescriptor = SamCodegenUtil.resolveSamAdapter(superCall.getResultingDescriptor());
1258 List<ResolvedValueArgument> valueArguments = superCall.getValueArgumentsByIndex();
1259 assert valueArguments != null : "Failed to arrange value arguments by index: " + superDescriptor;
1260
1261 List<JvmMethodParameterSignature> parameters = mapSignature(superDescriptor).getValueParameters();
1262
1263 int params = parameters.size();
1264 int args = valueArguments.size();
1265
1266 // Mapped parameters should consist of captured values plus all of valueArguments
1267 assert params >= args :
1268 String.format("Incorrect number of mapped parameters vs arguments: %d < %d for %s", params, args, descriptor);
1269
1270 // Include all captured values, i.e. those parameters for which there are no resolved value arguments
1271 for (int i = 0; i < params - args; i++) {
1272 JvmMethodParameterSignature parameter = parameters.get(i);
1273 JvmMethodParameterKind kind = parameter.getKind();
1274 if (kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL) continue;
1275 if (hasOuter && kind == JvmMethodParameterKind.OUTER) continue;
1276
1277 writeParameter(sw, JvmMethodParameterKind.SUPER_CALL_PARAM, parameter.getAsmType());
1278 }
1279
1280 if (isAnonymousObject(descriptor.getContainingDeclaration())) {
1281 // For anonymous objects, also add all real non-default value arguments passed to the super constructor
1282 for (int i = 0; i < args; i++) {
1283 ResolvedValueArgument valueArgument = valueArguments.get(i);
1284 JvmMethodParameterSignature parameter = parameters.get(params - args + i);
1285 if (!(valueArgument instanceof DefaultValueArgument)) {
1286 writeParameter(sw, JvmMethodParameterKind.SUPER_CALL_PARAM, parameter.getAsmType());
1287 }
1288 }
1289 }
1290 }
1291
1292 @Nullable
1293 private ResolvedCall<ConstructorDescriptor> findFirstDelegatingSuperCall(@NotNull ConstructorDescriptor descriptor) {
1294 ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
1295 while (true) {
1296 ResolvedCall<ConstructorDescriptor> next = getDelegationConstructorCall(bindingContext, descriptor);
1297 if (next == null) return null;
1298 descriptor = next.getResultingDescriptor();
1299 if (descriptor.getContainingDeclaration() != classDescriptor) return next;
1300 }
1301 }
1302
1303 @NotNull
1304 public JvmMethodSignature mapScriptSignature(@NotNull ScriptDescriptor script, @NotNull List<ScriptDescriptor> importedScripts) {
1305 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
1306
1307 sw.writeParametersStart();
1308
1309 for (ScriptDescriptor importedScript : importedScripts) {
1310 ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_SCRIPT, importedScript);
1311 assert descriptor != null : "Script not found: " + importedScript;
1312 writeParameter(sw, descriptor.getDefaultType());
1313 }
1314
1315 for (ValueParameterDescriptor valueParameter : script.getScriptCodeDescriptor().getValueParameters()) {
1316 writeParameter(sw, valueParameter.getType());
1317 }
1318
1319 writeVoidReturn(sw);
1320
1321 return sw.makeJvmMethodSignature("<init>");
1322 }
1323
1324 public Type getSharedVarType(DeclarationDescriptor descriptor) {
1325 if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
1326 return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
1327 }
1328 else if (descriptor instanceof PropertyDescriptor || descriptor instanceof FunctionDescriptor) {
1329 ReceiverParameterDescriptor receiverParameter = ((CallableDescriptor) descriptor).getExtensionReceiverParameter();
1330 assert receiverParameter != null : "Callable should have a receiver parameter: " + descriptor;
1331 return StackValue.sharedTypeForType(mapType(receiverParameter.getType()));
1332 }
1333 else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) {
1334 return StackValue.sharedTypeForType(mapType(((VariableDescriptor) descriptor).getType()));
1335 }
1336 return null;
1337 }
1338 }