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 org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
024 import org.jetbrains.kotlin.builtins.PrimitiveType;
025 import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor;
026 import org.jetbrains.kotlin.codegen.*;
027 import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
028 import org.jetbrains.kotlin.codegen.binding.MutableClosure;
029 import org.jetbrains.kotlin.codegen.binding.PsiCodegenPredictor;
030 import org.jetbrains.kotlin.codegen.context.CodegenContext;
031 import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
032 import org.jetbrains.kotlin.descriptors.*;
033 import org.jetbrains.kotlin.descriptors.annotations.Annotated;
034 import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
035 import org.jetbrains.kotlin.load.java.JvmAbi;
036 import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
037 import org.jetbrains.kotlin.load.kotlin.PackageClassUtils;
038 import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
039 import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeDeclarationsPackage;
040 import org.jetbrains.kotlin.name.*;
041 import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
042 import org.jetbrains.kotlin.psi.JetExpression;
043 import org.jetbrains.kotlin.psi.JetFile;
044 import org.jetbrains.kotlin.psi.JetFunctionLiteral;
045 import org.jetbrains.kotlin.psi.JetFunctionLiteralExpression;
046 import org.jetbrains.kotlin.resolve.BindingContext;
047 import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
048 import org.jetbrains.kotlin.resolve.DescriptorUtils;
049 import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage;
050 import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
051 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
052 import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
053 import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
054 import org.jetbrains.kotlin.resolve.constants.StringValue;
055 import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
056 import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
057 import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
058 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
059 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
060 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
061 import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
062 import org.jetbrains.kotlin.types.*;
063 import org.jetbrains.kotlin.types.expressions.OperatorConventions;
064 import org.jetbrains.org.objectweb.asm.Type;
065 import org.jetbrains.org.objectweb.asm.commons.Method;
066
067 import java.io.File;
068 import java.util.ArrayList;
069 import java.util.List;
070 import java.util.Map;
071
072 import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isUnit;
073 import static org.jetbrains.kotlin.codegen.AsmUtil.*;
074 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
075 import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
076 import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
077 import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
078 import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
079 import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getBuiltIns;
080 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER;
081 import static org.jetbrains.org.objectweb.asm.Opcodes.*;
082
083 public class JetTypeMapper {
084 private final BindingContext bindingContext;
085 private final ClassBuilderMode classBuilderMode;
086
087 public JetTypeMapper(@NotNull BindingContext bindingContext, @NotNull ClassBuilderMode classBuilderMode) {
088 this.bindingContext = bindingContext;
089 this.classBuilderMode = classBuilderMode;
090 }
091
092 @NotNull
093 public BindingContext getBindingContext() {
094 return bindingContext;
095 }
096
097 private enum JetTypeMapperMode {
098 /**
099 * foo.Bar is mapped to Lfoo/Bar;
100 */
101 IMPL,
102 /**
103 * kotlin.Int is mapped to I
104 */
105 VALUE,
106 /**
107 * kotlin.Int is mapped to Ljava/lang/Integer;
108 */
109 TYPE_PARAMETER,
110 /**
111 * kotlin.Int is mapped to Ljava/lang/Integer;
112 * No projections allowed in immediate arguments
113 */
114 SUPER_TYPE,
115 /**
116 * kotlin.reflect.KClass mapped to java.lang.Class
117 * Other types mapped as VALUE
118 */
119 VALUE_FOR_ANNOTATION,
120 /**
121 * kotlin.reflect.KClass mapped to java.lang.Class
122 * Other types mapped as TYPE_PARAMETER
123 */
124 TYPE_PARAMETER_FOR_ANNOTATION;
125
126 boolean isForAnnotation() {
127 return this == VALUE_FOR_ANNOTATION || this == TYPE_PARAMETER_FOR_ANNOTATION;
128 }
129 }
130
131 @NotNull
132 public Type mapOwner(@NotNull DeclarationDescriptor descriptor, boolean isInsideModule) {
133 if (isLocalFunction(descriptor)) {
134 return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
135 }
136
137 DeclarationDescriptor container = descriptor.getContainingDeclaration();
138 if (container instanceof PackageFragmentDescriptor) {
139 boolean effectiveInsideModule = isInsideModule && !NativeDeclarationsPackage.hasNativeAnnotation(descriptor);
140 return Type.getObjectType(internalNameForPackage(
141 (PackageFragmentDescriptor) container,
142 (CallableMemberDescriptor) descriptor,
143 effectiveInsideModule
144 ));
145 }
146 else if (container instanceof ClassDescriptor) {
147 return mapClass((ClassDescriptor) container);
148 }
149 else if (container instanceof ScriptDescriptor) {
150 return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container);
151 }
152 else {
153 throw new UnsupportedOperationException("Don't know how to map owner for " + descriptor);
154 }
155 }
156
157 @NotNull
158 private static String internalNameForPackage(
159 @NotNull PackageFragmentDescriptor packageFragment,
160 @NotNull CallableMemberDescriptor descriptor,
161 boolean insideModule
162 ) {
163 if (insideModule) {
164 JetFile file = DescriptorToSourceUtils.getContainingFile(descriptor);
165 if (file != null) {
166 return PackagePartClassUtils.getPackagePartInternalName(file);
167 }
168
169 CallableMemberDescriptor directMember = getDirectMember(descriptor);
170
171 if (directMember instanceof DeserializedCallableMemberDescriptor) {
172 FqName packagePartFqName = PackagePartClassUtils.getPackagePartFqName((DeserializedCallableMemberDescriptor) directMember);
173 return internalNameByFqNameWithoutInnerClasses(packagePartFqName);
174 }
175 }
176
177 return PackageClassUtils.getPackageClassInternalName(packageFragment.getFqName());
178 }
179
180 @NotNull
181 public Type mapReturnType(@NotNull CallableDescriptor descriptor) {
182 return mapReturnType(descriptor, null);
183 }
184
185 @NotNull
186 private Type mapReturnType(@NotNull CallableDescriptor descriptor, @Nullable BothSignatureWriter sw) {
187 JetType returnType = descriptor.getReturnType();
188 assert returnType != null : "Function has no return type: " + descriptor;
189
190 if (descriptor instanceof ConstructorDescriptor) {
191 return Type.VOID_TYPE;
192 }
193
194 if (isUnit(returnType) && !TypeUtils.isNullableType(returnType) && !(descriptor instanceof PropertyGetterDescriptor)) {
195 if (sw != null) {
196 sw.writeAsmType(Type.VOID_TYPE);
197 }
198 return Type.VOID_TYPE;
199 }
200 else if (descriptor instanceof FunctionDescriptor && forceBoxedReturnType((FunctionDescriptor) descriptor)) {
201 // TYPE_PARAMETER is a hack to automatically box the return type
202 //noinspection ConstantConditions
203 return mapType(descriptor.getReturnType(), sw, JetTypeMapperMode.TYPE_PARAMETER);
204 }
205 else if (DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration())) {
206 //noinspection ConstantConditions
207 return mapType(descriptor.getReturnType(), sw, JetTypeMapperMode.VALUE_FOR_ANNOTATION);
208 }
209 else {
210 return mapType(returnType, sw, JetTypeMapperMode.VALUE, Variance.OUT_VARIANCE);
211 }
212 }
213
214 @NotNull
215 private Type mapType(@NotNull JetType jetType, @NotNull JetTypeMapperMode mode) {
216 return mapType(jetType, null, mode);
217 }
218
219 @NotNull
220 public Type mapSupertype(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
221 return mapType(jetType, signatureVisitor, JetTypeMapperMode.SUPER_TYPE);
222 }
223
224 @NotNull
225 public Type mapTypeParameter(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
226 return mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
227 }
228
229 @NotNull
230 public Type mapClass(@NotNull ClassifierDescriptor classifier) {
231 return mapType(classifier.getDefaultType(), null, JetTypeMapperMode.IMPL);
232 }
233
234 @NotNull
235 public Type mapType(@NotNull JetType jetType) {
236 return mapType(jetType, null, JetTypeMapperMode.VALUE);
237 }
238
239 @NotNull
240 public Type mapType(@NotNull CallableDescriptor descriptor) {
241 //noinspection ConstantConditions
242 return mapType(descriptor.getReturnType());
243 }
244
245 @NotNull
246 public JvmMethodSignature mapAnnotationParameterSignature(@NotNull PropertyDescriptor descriptor) {
247 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
248 sw.writeReturnType();
249 mapType(descriptor.getType(), sw, JetTypeMapperMode.VALUE_FOR_ANNOTATION);
250 sw.writeReturnTypeEnd();
251 return sw.makeJvmMethodSignature(descriptor.getName().asString());
252 }
253
254 @NotNull
255 public Type mapType(@NotNull ClassifierDescriptor descriptor) {
256 return mapType(descriptor.getDefaultType());
257 }
258
259 @NotNull
260 private Type mapType(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor, @NotNull JetTypeMapperMode mode) {
261 return mapType(jetType, signatureVisitor, mode, Variance.INVARIANT);
262 }
263
264 @NotNull
265 private Type mapType(
266 @NotNull JetType jetType,
267 @Nullable BothSignatureWriter signatureVisitor,
268 @NotNull JetTypeMapperMode kind,
269 @NotNull Variance howThisTypeIsUsed
270 ) {
271 Type known = mapBuiltinType(jetType);
272
273 boolean projectionsAllowed = kind != JetTypeMapperMode.SUPER_TYPE;
274 if (known != null) {
275 if (kind == JetTypeMapperMode.VALUE || kind == JetTypeMapperMode.VALUE_FOR_ANNOTATION) {
276 return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
277 }
278 else if (kind == JetTypeMapperMode.TYPE_PARAMETER || kind == JetTypeMapperMode.SUPER_TYPE ||
279 kind == JetTypeMapperMode.TYPE_PARAMETER_FOR_ANNOTATION) {
280 return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed, projectionsAllowed);
281 }
282 else if (kind == JetTypeMapperMode.IMPL) {
283 // TODO: enable and fix tests
284 //throw new IllegalStateException("must not map known type to IMPL when not compiling builtins: " + jetType);
285 return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
286 }
287 else {
288 throw new IllegalStateException("unknown kind: " + kind);
289 }
290 }
291
292 TypeConstructor constructor = jetType.getConstructor();
293 DeclarationDescriptor descriptor = constructor.getDeclarationDescriptor();
294 if (constructor instanceof IntersectionTypeConstructor) {
295 jetType = CommonSupertypes.commonSupertype(new ArrayList<JetType>(constructor.getSupertypes()));
296 }
297
298 if (descriptor == null) {
299 throw new UnsupportedOperationException("no descriptor for type constructor of " + jetType);
300 }
301
302 if (ErrorUtils.isError(descriptor)) {
303 if (classBuilderMode != ClassBuilderMode.LIGHT_CLASSES) {
304 throw new IllegalStateException(generateErrorMessageForErrorType(jetType, descriptor));
305 }
306 Type asmType = Type.getObjectType("error/NonExistentClass");
307 if (signatureVisitor != null) {
308 signatureVisitor.writeAsmType(asmType);
309 }
310 return asmType;
311 }
312
313 if (descriptor instanceof ClassDescriptor && KotlinBuiltIns.isArray(jetType)) {
314 if (jetType.getArguments().size() != 1) {
315 throw new UnsupportedOperationException("arrays must have one type argument");
316 }
317 TypeProjection memberProjection = jetType.getArguments().get(0);
318 JetType memberType = memberProjection.getType();
319
320 Type arrayElementType;
321 if (memberProjection.getProjectionKind() == Variance.IN_VARIANCE) {
322 arrayElementType = AsmTypes.OBJECT_TYPE;
323 if (signatureVisitor != null) {
324 signatureVisitor.writeArrayType();
325 signatureVisitor.writeAsmType(arrayElementType);
326 signatureVisitor.writeArrayEnd();
327 }
328 }
329 else {
330 arrayElementType = boxType(mapType(memberType, kind));
331 if (signatureVisitor != null) {
332 signatureVisitor.writeArrayType();
333 JetTypeMapperMode newMode = kind.isForAnnotation() ?
334 JetTypeMapperMode.TYPE_PARAMETER_FOR_ANNOTATION :
335 JetTypeMapperMode.TYPE_PARAMETER;
336 mapType(memberType, signatureVisitor, newMode, memberProjection.getProjectionKind());
337 signatureVisitor.writeArrayEnd();
338 }
339 }
340
341 return Type.getType("[" + arrayElementType.getDescriptor());
342 }
343
344 if (descriptor instanceof ClassDescriptor) {
345 Type asmType = kind.isForAnnotation() && KotlinBuiltIns.isKClass((ClassDescriptor) descriptor) ?
346 AsmTypes.JAVA_CLASS_TYPE :
347 computeAsmType((ClassDescriptor) descriptor.getOriginal());
348 writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, projectionsAllowed);
349 return asmType;
350 }
351
352 if (descriptor instanceof TypeParameterDescriptor) {
353 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
354 Type type = mapType(typeParameterDescriptor.getUpperBounds().iterator().next(), kind);
355 if (signatureVisitor != null) {
356 signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), type);
357 }
358 return type;
359 }
360
361 throw new UnsupportedOperationException("Unknown type " + jetType);
362 }
363
364 @Nullable
365 private static Type mapBuiltinType(@NotNull JetType type) {
366 DeclarationDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
367 if (!(descriptor instanceof ClassDescriptor)) return null;
368
369 FqNameUnsafe fqName = DescriptorUtils.getFqName(descriptor);
370
371 PrimitiveType primitiveType = KotlinBuiltIns.getPrimitiveTypeByFqName(fqName);
372 if (primitiveType != null) {
373 Type asmType = Type.getType(JvmPrimitiveType.get(primitiveType).getDesc());
374 return TypeUtils.isNullableType(type) ? boxType(asmType) : asmType;
375 }
376
377 PrimitiveType arrayElementType = KotlinBuiltIns.getPrimitiveTypeByArrayClassFqName(fqName);
378 if (arrayElementType != null) {
379 return Type.getType("[" + JvmPrimitiveType.get(arrayElementType).getDesc());
380 }
381
382 ClassId classId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqName);
383 if (classId != null) {
384 return Type.getObjectType(JvmClassName.byClassId(classId).getInternalName());
385 }
386
387 return null;
388 }
389
390 @NotNull
391 private Type computeAsmType(@NotNull ClassDescriptor klass) {
392 Type alreadyComputedType = bindingContext.get(ASM_TYPE, klass);
393 if (alreadyComputedType != null) {
394 return alreadyComputedType;
395 }
396
397 Type asmType = Type.getObjectType(computeAsmTypeImpl(klass));
398 assert PsiCodegenPredictor.checkPredictedNameFromPsi(klass, asmType);
399 return asmType;
400 }
401
402 @NotNull
403 private String computeAsmTypeImpl(@NotNull ClassDescriptor klass) {
404 DeclarationDescriptor container = klass.getContainingDeclaration();
405
406 String name = SpecialNames.safeIdentifier(klass.getName()).getIdentifier();
407 if (container instanceof PackageFragmentDescriptor) {
408 FqName fqName = ((PackageFragmentDescriptor) container).getFqName();
409 return fqName.isRoot() ? name : fqName.asString().replace('.', '/') + '/' + name;
410 }
411
412 if (container instanceof ScriptDescriptor) {
413 return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container).getInternalName() + "$" + name;
414 }
415
416 assert container instanceof ClassDescriptor : "Unexpected container: " + container + " for " + klass;
417
418 String containerInternalName = computeAsmTypeImpl((ClassDescriptor) container);
419 return klass.getKind() == ClassKind.ENUM_ENTRY ? containerInternalName : containerInternalName + "$" + name;
420 }
421
422 @NotNull
423 public Type mapTraitImpl(@NotNull ClassDescriptor descriptor) {
424 return Type.getObjectType(mapType(descriptor).getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
425 }
426
427 @NotNull
428 private static String generateErrorMessageForErrorType(@NotNull JetType type, @NotNull DeclarationDescriptor descriptor) {
429 PsiElement declarationElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
430
431 if (declarationElement == null) {
432 return String.format(
433 "Error type encountered: %s (%s). " +
434 "One of the possible reasons may be that this type is not directly accessible from this module. " +
435 "To workaround this error, try adding an explicit dependency on the module or library which contains this type " +
436 "to the classpath",
437 type,
438 type.getClass().getSimpleName()
439 );
440 }
441
442 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
443 PsiElement parentDeclarationElement =
444 containingDeclaration != null ? DescriptorToSourceUtils.descriptorToDeclaration(containingDeclaration) : null;
445
446 return String.format(
447 "Error type encountered: %s (%s). Descriptor: %s. For declaration %s:%s in %s:%s",
448 type,
449 type.getClass().getSimpleName(),
450 descriptor,
451 declarationElement,
452 declarationElement.getText(),
453 parentDeclarationElement,
454 parentDeclarationElement != null ? parentDeclarationElement.getText() : "null"
455 );
456 }
457
458 private void writeGenericType(
459 BothSignatureWriter signatureVisitor,
460 Type asmType,
461 JetType jetType,
462 Variance howThisTypeIsUsed,
463 boolean projectionsAllowed
464 ) {
465 if (signatureVisitor != null) {
466 signatureVisitor.writeClassBegin(asmType);
467
468 List<TypeProjection> arguments = jetType.getArguments();
469 for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) {
470 TypeProjection argument = arguments.get(parameter.getIndex());
471
472 if (projectionsAllowed && argument.isStarProjection()) {
473 signatureVisitor.writeUnboundedWildcard();
474 }
475 else {
476 Variance projectionKind = projectionsAllowed
477 ? getEffectiveVariance(
478 parameter.getVariance(),
479 argument.getProjectionKind(),
480 howThisTypeIsUsed
481 )
482 : Variance.INVARIANT;
483 signatureVisitor.writeTypeArgument(projectionKind);
484
485 mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
486 signatureVisitor.writeTypeArgumentEnd();
487 }
488 }
489 signatureVisitor.writeClassEnd();
490 }
491 }
492
493 private static Variance getEffectiveVariance(Variance parameterVariance, Variance projectionKind, Variance howThisTypeIsUsed) {
494 // Return type must not contain wildcards
495 if (howThisTypeIsUsed == Variance.OUT_VARIANCE) return projectionKind;
496
497 if (parameterVariance == Variance.INVARIANT) {
498 return projectionKind;
499 }
500 if (projectionKind == Variance.INVARIANT) {
501 return parameterVariance;
502 }
503 if (parameterVariance == projectionKind) {
504 return parameterVariance;
505 }
506
507 // In<out X> = In<*>
508 // Out<in X> = Out<*>
509 return Variance.OUT_VARIANCE;
510 }
511
512 private Type mapKnownAsmType(
513 JetType jetType,
514 Type asmType,
515 @Nullable BothSignatureWriter signatureVisitor,
516 @NotNull Variance howThisTypeIsUsed
517 ) {
518 return mapKnownAsmType(jetType, asmType, signatureVisitor, howThisTypeIsUsed, true);
519 }
520
521 private Type mapKnownAsmType(
522 JetType jetType,
523 Type asmType,
524 @Nullable BothSignatureWriter signatureVisitor,
525 @NotNull Variance howThisTypeIsUsed,
526 boolean allowProjections
527 ) {
528 if (signatureVisitor != null) {
529 if (jetType.getArguments().isEmpty()) {
530 signatureVisitor.writeAsmType(asmType);
531 }
532 else {
533 writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, allowProjections);
534 }
535 }
536 return asmType;
537 }
538
539 @NotNull
540 public CallableMethod mapToCallableMethod(
541 @NotNull FunctionDescriptor descriptor,
542 boolean superCall,
543 @NotNull CodegenContext<?> context
544 ) {
545 DeclarationDescriptor functionParent = descriptor.getOriginal().getContainingDeclaration();
546
547 FunctionDescriptor functionDescriptor = unwrapFakeOverride(descriptor.getOriginal());
548
549 JvmMethodSignature signature;
550 Type owner;
551 Type ownerForDefaultImpl;
552 Type ownerForDefaultParam;
553 int invokeOpcode;
554 Type thisClass;
555
556 if (functionParent instanceof ClassDescriptor) {
557 FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor);
558
559 ClassDescriptor currentOwner = (ClassDescriptor) functionParent;
560 ClassDescriptor declarationOwner = (ClassDescriptor) declarationFunctionDescriptor.getContainingDeclaration();
561
562 boolean originalIsInterface = isInterface(declarationOwner);
563 boolean currentIsInterface = isInterface(currentOwner);
564
565 boolean isInterface = currentIsInterface && originalIsInterface;
566
567 ClassDescriptor ownerForDefault = (ClassDescriptor) findBaseDeclaration(functionDescriptor).getContainingDeclaration();
568 ownerForDefaultParam = mapClass(ownerForDefault);
569 ownerForDefaultImpl = isInterface(ownerForDefault) ? mapTraitImpl(ownerForDefault) : ownerForDefaultParam;
570
571 if (isInterface && superCall) {
572 thisClass = mapClass(currentOwner);
573 if (declarationOwner instanceof JavaClassDescriptor) {
574 invokeOpcode = INVOKESPECIAL;
575 signature = mapSignature(functionDescriptor);
576 owner = thisClass;
577 }
578 else {
579 invokeOpcode = INVOKESTATIC;
580 signature = mapSignature(functionDescriptor, OwnerKind.TRAIT_IMPL);
581 owner = mapTraitImpl(currentOwner);
582 }
583 }
584 else {
585 if (isStaticDeclaration(functionDescriptor) ||
586 isAccessor(functionDescriptor) ||
587 AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor)) {
588 invokeOpcode = INVOKESTATIC;
589 }
590 else if (isInterface) {
591 invokeOpcode = INVOKEINTERFACE;
592 }
593 else {
594 boolean isPrivateFunInvocation = Visibilities.isPrivate(functionDescriptor.getVisibility());
595 invokeOpcode = superCall || isPrivateFunInvocation ? INVOKESPECIAL : INVOKEVIRTUAL;
596 }
597
598 signature = mapSignature(functionDescriptor.getOriginal());
599
600 ClassDescriptor receiver = (currentIsInterface && !originalIsInterface) || currentOwner instanceof FunctionClassDescriptor
601 ? declarationOwner
602 : currentOwner;
603 owner = mapClass(receiver);
604 thisClass = owner;
605 }
606 }
607 else {
608 signature = mapSignature(functionDescriptor.getOriginal());
609 owner = mapOwner(functionDescriptor, isCallInsideSameModuleAsDeclared(functionDescriptor, context, getOutDirectory()));
610 ownerForDefaultParam = owner;
611 ownerForDefaultImpl = owner;
612 if (functionParent instanceof PackageFragmentDescriptor) {
613 invokeOpcode = INVOKESTATIC;
614 thisClass = null;
615 }
616 else if (functionDescriptor instanceof ConstructorDescriptor) {
617 invokeOpcode = INVOKESPECIAL;
618 thisClass = null;
619 }
620 else {
621 invokeOpcode = INVOKEVIRTUAL;
622 thisClass = owner;
623 }
624 }
625
626 Type calleeType = isLocalFunction(functionDescriptor) ? owner : null;
627
628 Type receiverParameterType;
629 ReceiverParameterDescriptor receiverParameter = functionDescriptor.getOriginal().getExtensionReceiverParameter();
630 if (receiverParameter != null) {
631 receiverParameterType = mapType(receiverParameter.getType());
632 }
633 else {
634 receiverParameterType = null;
635 }
636 return new CallableMethod(
637 owner, ownerForDefaultImpl, ownerForDefaultParam, signature, invokeOpcode,
638 thisClass, receiverParameterType, calleeType);
639 }
640
641 public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
642 return descriptor instanceof AccessorForCallableDescriptor<?>;
643 }
644
645 @NotNull
646 private static FunctionDescriptor findAnyDeclaration(@NotNull FunctionDescriptor function) {
647 if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
648 return function;
649 }
650 return findBaseDeclaration(function);
651 }
652
653 @NotNull
654 private static FunctionDescriptor findBaseDeclaration(@NotNull FunctionDescriptor function) {
655 if (function.getOverriddenDescriptors().isEmpty()) {
656 return function;
657 }
658 else {
659 // TODO: prefer class to interface
660 return findBaseDeclaration(function.getOverriddenDescriptors().iterator().next());
661 }
662 }
663
664 @NotNull
665 private String mapFunctionName(@NotNull FunctionDescriptor descriptor) {
666 String platformName = getPlatformName(descriptor);
667 if (platformName != null) return platformName;
668
669 if (descriptor instanceof PropertyAccessorDescriptor) {
670 PropertyDescriptor property = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty();
671 if (isAnnotationClass(property.getContainingDeclaration())) {
672 return property.getName().asString();
673 }
674
675 boolean isAccessor = property instanceof AccessorForPropertyDescriptor;
676 Name propertyName = isAccessor
677 ? Name.identifier(((AccessorForPropertyDescriptor) property).getIndexedAccessorSuffix())
678 : property.getName();
679
680 String accessorName = descriptor instanceof PropertyGetterDescriptor
681 ? PropertyCodegen.getterName(propertyName)
682 : PropertyCodegen.setterName(propertyName);
683
684 return isAccessor ? "access$" + accessorName : accessorName;
685 }
686 else if (isFunctionLiteral(descriptor)) {
687 PsiElement element = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor);
688 if (element instanceof JetFunctionLiteral) {
689 PsiElement expression = element.getParent();
690 if (expression instanceof JetFunctionLiteralExpression) {
691 SamType samType = bindingContext.get(SAM_VALUE, (JetExpression) expression);
692 if (samType != null) {
693 return samType.getAbstractMethod().getName().asString();
694 }
695 }
696 }
697
698 return OperatorConventions.INVOKE.asString();
699 }
700 else if (isLocalFunction(descriptor) || isFunctionExpression(descriptor)) {
701 return OperatorConventions.INVOKE.asString();
702 }
703 else {
704 return descriptor.getName().asString();
705 }
706 }
707
708 @Nullable
709 private static String getPlatformName(@NotNull Annotated descriptor) {
710 AnnotationDescriptor platformNameAnnotation = descriptor.getAnnotations().findAnnotation(new FqName("kotlin.platform.platformName"));
711 if (platformNameAnnotation == null) return null;
712
713 Map<ValueParameterDescriptor, CompileTimeConstant<?>> arguments = platformNameAnnotation.getAllValueArguments();
714 if (arguments.isEmpty()) return null;
715
716 CompileTimeConstant<?> name = arguments.values().iterator().next();
717 if (!(name instanceof StringValue)) return null;
718
719 return ((StringValue) name).getValue();
720 }
721
722 @NotNull
723 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor descriptor) {
724 return mapSignature(descriptor, OwnerKind.IMPLEMENTATION);
725 }
726
727 @NotNull
728 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind) {
729 if (f instanceof ConstructorDescriptor) {
730 return mapSignature(f, kind, f.getOriginal().getValueParameters());
731 }
732 return mapSignature(f, kind, f.getValueParameters());
733 }
734
735 @NotNull
736 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind,
737 List<ValueParameterDescriptor> valueParameters) {
738 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
739
740 if (f instanceof ConstructorDescriptor) {
741 sw.writeParametersStart();
742 writeAdditionalConstructorParameters((ConstructorDescriptor) f, sw);
743
744 for (ValueParameterDescriptor parameter : valueParameters) {
745 writeParameter(sw, parameter.getType());
746 }
747
748 writeVoidReturn(sw);
749 }
750 else {
751 writeFormalTypeParameters(getDirectMember(f).getTypeParameters(), sw);
752
753 sw.writeParametersStart();
754 writeThisIfNeeded(f, kind, sw);
755
756 ReceiverParameterDescriptor receiverParameter = f.getExtensionReceiverParameter();
757 if (receiverParameter != null) {
758 writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.getType());
759 }
760
761 for (ValueParameterDescriptor parameter : valueParameters) {
762 writeParameter(sw, parameter.getType());
763 }
764
765 sw.writeReturnType();
766 mapReturnType(f, sw);
767 sw.writeReturnTypeEnd();
768 }
769
770 return sw.makeJvmMethodSignature(mapFunctionName(f));
771 }
772
773 @NotNull
774 public static String getDefaultDescriptor(@NotNull Method method, @Nullable String dispatchReceiverDescriptor, boolean isExtension) {
775 String descriptor = method.getDescriptor();
776 int argumentsCount = Type.getArgumentTypes(descriptor).length;
777 if (isExtension) {
778 argumentsCount--;
779 }
780 int maskArgumentsCount = (argumentsCount + Integer.SIZE - 1) / Integer.SIZE;
781 String additionalArgs = StringUtil.repeat(Type.INT_TYPE.getDescriptor(), maskArgumentsCount);
782 if (isConstructor(method)) {
783 additionalArgs += DEFAULT_CONSTRUCTOR_MARKER.getDescriptor();
784 }
785 String result = descriptor.replace(")", additionalArgs + ")");
786 if (dispatchReceiverDescriptor != null && !isConstructor(method)) {
787 return result.replace("(", "(" + dispatchReceiverDescriptor);
788 }
789 return result;
790 }
791
792 public ClassBuilderMode getClassBuilderMode() {
793 return classBuilderMode;
794 }
795
796 private static boolean isConstructor(@NotNull Method method) {
797 return "<init>".equals(method.getName());
798 }
799
800 @NotNull
801 public Method mapDefaultMethod(@NotNull FunctionDescriptor functionDescriptor, @NotNull OwnerKind kind, @NotNull CodegenContext<?> context) {
802 Method jvmSignature = mapSignature(functionDescriptor, kind).getAsmMethod();
803 Type ownerType = mapOwner(functionDescriptor, isCallInsideSameModuleAsDeclared(functionDescriptor, context, getOutDirectory()));
804 boolean isConstructor = isConstructor(jvmSignature);
805 String descriptor = getDefaultDescriptor(jvmSignature,
806 isStaticMethod(kind, functionDescriptor) || isConstructor ? null : ownerType.getDescriptor(),
807 functionDescriptor.getExtensionReceiverParameter() != null);
808
809 return new Method(isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, descriptor);
810 }
811
812 /**
813 * @return true iff a given function descriptor should be compiled to a method with boxed return type regardless of whether return type
814 * of that descriptor is nullable or not. This happens when a function returning a value of a primitive type overrides another function
815 * 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
816 * this class from Java since javac issues errors when loading the class (incompatible return types)
817 */
818 private static boolean forceBoxedReturnType(@NotNull FunctionDescriptor descriptor) {
819 //noinspection ConstantConditions
820 if (!KotlinBuiltIns.isPrimitiveType(descriptor.getReturnType())) return false;
821
822 for (FunctionDescriptor overridden : getAllOverriddenDescriptors(descriptor)) {
823 //noinspection ConstantConditions
824 if (!KotlinBuiltIns.isPrimitiveType(overridden.getOriginal().getReturnType())) return true;
825 }
826
827 return false;
828 }
829
830 private static void writeVoidReturn(@NotNull BothSignatureWriter sw) {
831 sw.writeReturnType();
832 sw.writeAsmType(Type.VOID_TYPE);
833 sw.writeReturnTypeEnd();
834 }
835
836 @Nullable
837 public String mapFieldSignature(@NotNull JetType backingFieldType) {
838 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
839 mapType(backingFieldType, sw, JetTypeMapperMode.VALUE);
840 return sw.makeJavaGenericSignature();
841 }
842
843 private void writeThisIfNeeded(
844 @NotNull CallableMemberDescriptor descriptor,
845 @NotNull OwnerKind kind,
846 @NotNull BothSignatureWriter sw
847 ) {
848 ClassDescriptor thisType;
849 if (kind == OwnerKind.TRAIT_IMPL) {
850 thisType = getTraitImplThisParameterClass((ClassDescriptor) descriptor.getContainingDeclaration());
851 }
852 else if (isAccessor(descriptor) && descriptor.getDispatchReceiverParameter() != null) {
853 thisType = (ClassDescriptor) descriptor.getContainingDeclaration();
854 }
855 else return;
856
857 writeParameter(sw, JvmMethodParameterKind.THIS, thisType.getDefaultType());
858 }
859
860 @NotNull
861 private static ClassDescriptor getTraitImplThisParameterClass(@NotNull ClassDescriptor traitDescriptor) {
862 for (ClassDescriptor descriptor : DescriptorUtils.getSuperclassDescriptors(traitDescriptor)) {
863 if (descriptor.getKind() != ClassKind.INTERFACE) {
864 return descriptor;
865 }
866 }
867 return traitDescriptor;
868 }
869
870 public void writeFormalTypeParameters(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull BothSignatureWriter sw) {
871 for (TypeParameterDescriptor typeParameter : typeParameters) {
872 writeFormalTypeParameter(typeParameter, sw);
873 }
874 }
875
876 private void writeFormalTypeParameter(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull BothSignatureWriter sw) {
877 if (classBuilderMode == ClassBuilderMode.LIGHT_CLASSES && typeParameterDescriptor.getName().isSpecial()) {
878 // If a type parameter has no name, the code below fails, but it should recover in case of light classes
879 return;
880 }
881
882 sw.writeFormalTypeParameter(typeParameterDescriptor.getName().asString());
883
884 classBound:
885 {
886 sw.writeClassBound();
887
888 for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
889 if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
890 if (!isInterface(jetType)) {
891 mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
892 break classBound;
893 }
894 }
895 }
896
897 // "extends Object" is optional according to ClassFileFormat-Java5.pdf
898 // but javac complaints to signature:
899 // <P:>Ljava/lang/Object;
900 // TODO: avoid writing java/lang/Object if interface list is not empty
901 }
902 sw.writeClassBoundEnd();
903
904 for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
905 ClassifierDescriptor classifier = jetType.getConstructor().getDeclarationDescriptor();
906 if (classifier instanceof ClassDescriptor) {
907 if (isInterface(jetType)) {
908 sw.writeInterfaceBound();
909 mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
910 sw.writeInterfaceBoundEnd();
911 }
912 }
913 else if (classifier instanceof TypeParameterDescriptor) {
914 sw.writeInterfaceBound();
915 mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
916 sw.writeInterfaceBoundEnd();
917 }
918 else {
919 throw new UnsupportedOperationException("Unknown classifier: " + classifier);
920 }
921 }
922 }
923
924 private void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JetType type) {
925 writeParameter(sw, JvmMethodParameterKind.VALUE, type);
926 }
927
928 private void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JvmMethodParameterKind kind, @NotNull JetType type) {
929 sw.writeParameterType(kind);
930 mapType(type, sw, JetTypeMapperMode.VALUE);
931 sw.writeParameterTypeEnd();
932 }
933
934 private static void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JvmMethodParameterKind kind, @NotNull Type type) {
935 sw.writeParameterType(kind);
936 sw.writeAsmType(type);
937 sw.writeParameterTypeEnd();
938 }
939
940 private void writeAdditionalConstructorParameters(@NotNull ConstructorDescriptor descriptor, @NotNull BothSignatureWriter sw) {
941 MutableClosure closure = bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration());
942
943 ClassDescriptor captureThis = getDispatchReceiverParameterForConstructorCall(descriptor, closure);
944 if (captureThis != null) {
945 writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType());
946 }
947
948 JetType captureReceiverType = closure != null ? closure.getCaptureReceiverType() : null;
949 if (captureReceiverType != null) {
950 writeParameter(sw, JvmMethodParameterKind.RECEIVER, captureReceiverType);
951 }
952
953 ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
954 if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
955 writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, getBuiltIns(descriptor).getStringType());
956 writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, getBuiltIns(descriptor).getIntType());
957 }
958
959 if (closure == null) return;
960
961 for (DeclarationDescriptor variableDescriptor : closure.getCaptureVariables().keySet()) {
962 Type type;
963 if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) {
964 Type sharedVarType = getSharedVarType(variableDescriptor);
965 if (sharedVarType == null) {
966 sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType());
967 }
968 type = sharedVarType;
969 }
970 else if (isLocalFunction(variableDescriptor)) {
971 //noinspection CastConflictsWithInstanceof
972 type = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) variableDescriptor);
973 }
974 else {
975 type = null;
976 }
977
978 if (type != null) {
979 closure.setCapturedParameterOffsetInConstructor(variableDescriptor, sw.getCurrentSignatureSize() + 1);
980 writeParameter(sw, JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE, type);
981 }
982 }
983
984 // We may generate a slightly wrong signature for a local class / anonymous object in light classes mode but we don't care,
985 // because such classes are not accessible from the outside world
986 if (classBuilderMode == ClassBuilderMode.FULL) {
987 ResolvedCall<ConstructorDescriptor> superCall = findFirstDelegatingSuperCall(descriptor);
988 if (superCall == null) return;
989 writeSuperConstructorCallParameters(sw, descriptor, superCall, captureThis != null);
990 }
991 }
992
993 private void writeSuperConstructorCallParameters(
994 @NotNull BothSignatureWriter sw,
995 @NotNull ConstructorDescriptor descriptor,
996 @NotNull ResolvedCall<ConstructorDescriptor> superCall,
997 boolean hasOuter
998 ) {
999 ConstructorDescriptor superDescriptor = SamCodegenUtil.resolveSamAdapter(superCall.getResultingDescriptor());
1000 List<ResolvedValueArgument> valueArguments = superCall.getValueArgumentsByIndex();
1001 assert valueArguments != null : "Failed to arrange value arguments by index: " + superDescriptor;
1002
1003 List<JvmMethodParameterSignature> parameters = mapSignature(superDescriptor).getValueParameters();
1004
1005 int params = parameters.size();
1006 int args = valueArguments.size();
1007
1008 // Mapped parameters should consist of captured values plus all of valueArguments
1009 assert params >= args :
1010 String.format("Incorrect number of mapped parameters vs arguments: %d < %d for %s", params, args, descriptor);
1011
1012 // Include all captured values, i.e. those parameters for which there are no resolved value arguments
1013 for (int i = 0; i < params - args; i++) {
1014 JvmMethodParameterSignature parameter = parameters.get(i);
1015 JvmMethodParameterKind kind = parameter.getKind();
1016 if (kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL) continue;
1017 if (hasOuter && kind == JvmMethodParameterKind.OUTER) continue;
1018
1019 writeParameter(sw, JvmMethodParameterKind.SUPER_CALL_PARAM, parameter.getAsmType());
1020 }
1021
1022 if (isAnonymousObject(descriptor.getContainingDeclaration())) {
1023 // For anonymous objects, also add all real non-default value arguments passed to the super constructor
1024 for (int i = 0; i < args; i++) {
1025 ResolvedValueArgument valueArgument = valueArguments.get(i);
1026 JvmMethodParameterSignature parameter = parameters.get(params - args + i);
1027 if (!(valueArgument instanceof DefaultValueArgument)) {
1028 writeParameter(sw, JvmMethodParameterKind.SUPER_CALL_PARAM, parameter.getAsmType());
1029 }
1030 }
1031 }
1032 }
1033
1034 @Nullable
1035 private ResolvedCall<ConstructorDescriptor> findFirstDelegatingSuperCall(@NotNull ConstructorDescriptor descriptor) {
1036 ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
1037 while (true) {
1038 ResolvedCall<ConstructorDescriptor> next = getDelegationConstructorCall(bindingContext, descriptor);
1039 if (next == null) return null;
1040 descriptor = next.getResultingDescriptor();
1041 if (descriptor.getContainingDeclaration() != classDescriptor) return next;
1042 }
1043 }
1044
1045 @NotNull
1046 public JvmMethodSignature mapScriptSignature(@NotNull ScriptDescriptor script, @NotNull List<ScriptDescriptor> importedScripts) {
1047 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
1048
1049 sw.writeParametersStart();
1050
1051 for (ScriptDescriptor importedScript : importedScripts) {
1052 ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_SCRIPT, importedScript);
1053 assert descriptor != null : "Script not found: " + importedScript;
1054 writeParameter(sw, descriptor.getDefaultType());
1055 }
1056
1057 for (ValueParameterDescriptor valueParameter : script.getScriptCodeDescriptor().getValueParameters()) {
1058 writeParameter(sw, valueParameter.getType());
1059 }
1060
1061 writeVoidReturn(sw);
1062
1063 return sw.makeJvmMethodSignature("<init>");
1064 }
1065
1066 @NotNull
1067 public CallableMethod mapToCallableMethod(@NotNull ConstructorDescriptor descriptor) {
1068 JvmMethodSignature method = mapSignature(descriptor);
1069 ClassDescriptor container = descriptor.getContainingDeclaration();
1070 Type owner = mapClass(container);
1071 if (owner.getSort() != Type.OBJECT) {
1072 throw new IllegalStateException("type must have been mapped to object: " + container.getDefaultType() + ", actual: " + owner);
1073 }
1074 return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL, null, null, null);
1075 }
1076
1077 public Type getSharedVarType(DeclarationDescriptor descriptor) {
1078 if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
1079 return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
1080 }
1081 else if (descriptor instanceof PropertyDescriptor || descriptor instanceof FunctionDescriptor) {
1082 ReceiverParameterDescriptor receiverParameter = ((CallableDescriptor) descriptor).getExtensionReceiverParameter();
1083 assert receiverParameter != null : "Callable should have a receiver parameter: " + descriptor;
1084 return StackValue.sharedTypeForType(mapType(receiverParameter.getType()));
1085 }
1086 else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) {
1087 return StackValue.sharedTypeForType(mapType(((VariableDescriptor) descriptor).getType()));
1088 }
1089 return null;
1090 }
1091
1092 // TODO Temporary hack until modules infrastructure is implemented. See JetTypeMapperWithOutDirectory for details
1093 @Nullable
1094 protected File getOutDirectory() {
1095 return null;
1096 }
1097 }