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