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