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, false);
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 return mapType(jetType, signatureVisitor, kind, howThisTypeIsUsed, false);
232 }
233
234 @NotNull
235 public Type mapType(
236 @NotNull JetType jetType,
237 @Nullable BothSignatureWriter signatureVisitor,
238 @NotNull JetTypeMapperMode kind,
239 @NotNull Variance howThisTypeIsUsed,
240 boolean arrayParameter
241 ) {
242 Type known = null;
243 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
244
245 if (mapBuiltinsToJava) {
246 if (descriptor instanceof ClassDescriptor) {
247 known = KotlinToJavaTypesMap.getInstance().getJavaAnalog(jetType);
248 }
249 }
250
251 if (known != null) {
252 if (kind == JetTypeMapperMode.VALUE) {
253 return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
254 }
255 else if (kind == JetTypeMapperMode.TYPE_PARAMETER) {
256 return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed, arrayParameter);
257 }
258 else if (kind == JetTypeMapperMode.TRAIT_IMPL) {
259 throw new IllegalStateException("TRAIT_IMPL is not possible for " + jetType);
260 }
261 else if (kind == JetTypeMapperMode.IMPL) {
262 //noinspection ConstantConditions
263 if (mapBuiltinsToJava) {
264 // TODO: enable and fix tests
265 //throw new IllegalStateException("must not map known type to IMPL when not compiling builtins: " + jetType);
266 }
267 return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
268 }
269 else {
270 throw new IllegalStateException("unknown kind: " + kind);
271 }
272 }
273
274 TypeConstructor constructor = jetType.getConstructor();
275 if (constructor instanceof IntersectionTypeConstructor) {
276 jetType = CommonSupertypes.commonSupertype(new ArrayList<JetType>(constructor.getSupertypes()));
277 }
278
279 if (descriptor == null) {
280 throw new UnsupportedOperationException("no descriptor for type constructor of " + jetType);
281 }
282
283 if (ErrorUtils.isError(descriptor)) {
284 if (classBuilderMode != ClassBuilderMode.SIGNATURES) {
285 throw new IllegalStateException(generateErrorMessageForErrorType(descriptor));
286 }
287 Type asmType = Type.getObjectType("error/NonExistentClass");
288 if (signatureVisitor != null) {
289 signatureVisitor.writeAsmType(asmType, true);
290 }
291 checkValidType(asmType);
292 return asmType;
293 }
294
295 if (mapBuiltinsToJava && descriptor instanceof ClassDescriptor && KotlinBuiltIns.getInstance().isArray(jetType)) {
296 if (jetType.getArguments().size() != 1) {
297 throw new UnsupportedOperationException("arrays must have one type argument");
298 }
299 TypeProjection memberProjection = jetType.getArguments().get(0);
300 JetType memberType = memberProjection.getType();
301
302 if (signatureVisitor != null) {
303 signatureVisitor.writeArrayType(jetType.isNullable(), memberProjection.getProjectionKind());
304 mapType(memberType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER, memberProjection.getProjectionKind(), true);
305 signatureVisitor.writeArrayEnd();
306 }
307
308 Type r;
309 if (!isGenericsArray(jetType)) {
310 r = Type.getType("[" + boxType(mapType(memberType, kind)).getDescriptor());
311 }
312 else {
313 r = AsmTypeConstants.JAVA_ARRAY_GENERIC_TYPE;
314 }
315 checkValidType(r);
316 return r;
317 }
318
319 if (descriptor instanceof ClassDescriptor) {
320 JvmClassName name = getJvmInternalName(bindingTrace, descriptor);
321 Type asmType;
322 if (kind == JetTypeMapperMode.TRAIT_IMPL) {
323 asmType = Type.getObjectType(name.getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
324 }
325 else {
326 asmType = name.getAsmType();
327 }
328 boolean forceReal = KotlinToJavaTypesMap.getInstance().isForceReal(name);
329
330 writeGenericType(signatureVisitor, asmType, jetType, forceReal, howThisTypeIsUsed);
331
332 checkValidType(asmType);
333 return asmType;
334 }
335
336 if (descriptor instanceof TypeParameterDescriptor) {
337 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
338 Type type = mapType(typeParameterDescriptor.getUpperBoundsAsType(), kind);
339 if (signatureVisitor != null) {
340 signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), jetType.isNullable(), type);
341 }
342 checkValidType(type);
343 return type;
344 }
345
346 throw new UnsupportedOperationException("Unknown type " + jetType);
347 }
348
349 private String generateErrorMessageForErrorType(@NotNull DeclarationDescriptor descriptor) {
350 PsiElement declarationElement = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor);
351 PsiElement parentDeclarationElement = null;
352 if (declarationElement != null) {
353 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
354 if (containingDeclaration != null) {
355 parentDeclarationElement = BindingContextUtils.descriptorToDeclaration(bindingContext, containingDeclaration);
356 }
357 }
358
359 return String.format("Error types are not allowed when classBuilderMode = %s. For declaration %s:%s in %s:%s",
360 classBuilderMode,
361 declarationElement,
362 declarationElement != null ? declarationElement.getText() : "null",
363 parentDeclarationElement,
364 parentDeclarationElement != null ? parentDeclarationElement.getText() : "null");
365 }
366
367 private void writeGenericType(
368 BothSignatureWriter signatureVisitor,
369 Type asmType,
370 JetType jetType,
371 boolean forceReal,
372 Variance howThisTypeIsUsed
373 ) {
374 if (signatureVisitor != null) {
375 String kotlinTypeName = getKotlinTypeNameForSignature(jetType, asmType);
376 signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable(), forceReal, kotlinTypeName);
377
378 List<TypeProjection> arguments = jetType.getArguments();
379 for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) {
380 TypeProjection argument = arguments.get(parameter.getIndex());
381
382 Variance projectionKindForKotlin = argument.getProjectionKind();
383 Variance projectionKindForJava = getEffectiveVariance(
384 parameter.getVariance(),
385 projectionKindForKotlin,
386 howThisTypeIsUsed
387 );
388 signatureVisitor.writeTypeArgument(projectionKindForKotlin, projectionKindForJava);
389
390 mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
391 signatureVisitor.writeTypeArgumentEnd();
392 }
393 signatureVisitor.writeClassEnd();
394 }
395 }
396
397 private static Variance getEffectiveVariance(Variance parameterVariance, Variance projectionKind, Variance howThisTypeIsUsed) {
398 // Return type must not contain wildcards
399 if (howThisTypeIsUsed == Variance.OUT_VARIANCE) return projectionKind;
400
401 if (parameterVariance == Variance.INVARIANT) {
402 return projectionKind;
403 }
404 if (projectionKind == Variance.INVARIANT) {
405 return parameterVariance;
406 }
407 if (parameterVariance == projectionKind) {
408 return parameterVariance;
409 }
410
411 // In<out X> = In<*>
412 // Out<in X> = Out<*>
413 return Variance.OUT_VARIANCE;
414 }
415
416 private Type mapKnownAsmType(
417 JetType jetType,
418 Type asmType,
419 @Nullable BothSignatureWriter signatureVisitor,
420 @NotNull Variance howThisTypeIsUsed
421 ) {
422 return mapKnownAsmType(jetType, asmType, signatureVisitor, howThisTypeIsUsed, false);
423 }
424
425 private Type mapKnownAsmType(
426 JetType jetType,
427 Type asmType,
428 @Nullable BothSignatureWriter signatureVisitor,
429 @NotNull Variance howThisTypeIsUsed,
430 boolean arrayParameter
431 ) {
432 if (signatureVisitor != null) {
433 if (jetType.getArguments().isEmpty()) {
434 if (arrayParameter
435 && (howThisTypeIsUsed == Variance.IN_VARIANCE)) {
436 asmType = AsmTypeConstants.OBJECT_TYPE;
437 }
438 String kotlinTypeName = getKotlinTypeNameForSignature(jetType, asmType, arrayParameter);
439 signatureVisitor.writeAsmType(asmType, jetType.isNullable(), kotlinTypeName);
440 }
441 else {
442 writeGenericType(signatureVisitor, asmType, jetType, false, howThisTypeIsUsed);
443 }
444 }
445 checkValidType(asmType);
446 return asmType;
447 }
448
449 @Nullable
450 private static String getKotlinTypeNameForSignature(@NotNull JetType jetType, @NotNull Type asmType) {
451 return getKotlinTypeNameForSignature(jetType, asmType, false);
452 }
453
454 @Nullable
455 private static String getKotlinTypeNameForSignature(@NotNull JetType jetType, @NotNull Type asmType, boolean arrayParameter) {
456 ClassifierDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
457 if (descriptor == null) return null;
458 if (asmType.getSort() != Type.OBJECT) return null;
459
460 JvmClassName jvmClassName = JvmClassName.byType(asmType);
461 if ((arrayParameter && JavaToKotlinClassMap.getInstance().mapPlatformClass(jvmClassName.getFqName()).size() >= 1)
462 || ((!arrayParameter) && JavaToKotlinClassMap.getInstance().mapPlatformClass(jvmClassName.getFqName()).size() > 1)) {
463 return JvmClassName.byClassDescriptor(descriptor).getSignatureName();
464 }
465 return null;
466 }
467
468 private void checkValidType(@NotNull Type type) {
469 if (!mapBuiltinsToJava) {
470 String descriptor = type.getDescriptor();
471 if (!descriptor.equals("Ljava/lang/Object;")) {
472 if (descriptor.startsWith("Ljava/")) {
473 throw new IllegalStateException("builtins must not reference java.* classes: " + descriptor);
474 }
475 }
476 }
477 }
478
479 @NotNull
480 public CallableMethod mapToCallableMethod(
481 @NotNull FunctionDescriptor functionDescriptor,
482 boolean superCall,
483 boolean isInsideClass,
484 boolean isInsideModule,
485 OwnerKind kind
486 ) {
487 DeclarationDescriptor functionParent = functionDescriptor.getOriginal().getContainingDeclaration();
488
489 functionDescriptor = unwrapFakeOverride(functionDescriptor);
490
491 JvmMethodSignature descriptor = mapSignature(functionDescriptor.getOriginal(), true, kind);
492 JvmClassName owner;
493 JvmClassName ownerForDefaultImpl;
494 JvmClassName ownerForDefaultParam;
495 int invokeOpcode;
496 JvmClassName thisClass;
497 if (functionParent instanceof NamespaceDescriptor) {
498 assert !superCall;
499 owner = jvmClassNameForNamespace((NamespaceDescriptor) functionParent, functionDescriptor, isInsideModule);
500 ownerForDefaultImpl = ownerForDefaultParam = owner;
501 invokeOpcode = INVOKESTATIC;
502 thisClass = null;
503 }
504 else if (functionDescriptor instanceof ConstructorDescriptor) {
505 assert !superCall;
506 ClassDescriptor containingClass = (ClassDescriptor) functionParent;
507 owner = JvmClassName.byType(mapType(containingClass.getDefaultType(), JetTypeMapperMode.IMPL));
508 ownerForDefaultImpl = ownerForDefaultParam = owner;
509 invokeOpcode = INVOKESPECIAL;
510 thisClass = null;
511 }
512 else if (functionParent instanceof ScriptDescriptor) {
513 thisClass = owner =
514 ownerForDefaultParam = ownerForDefaultImpl = classNameForScriptDescriptor(bindingContext, (ScriptDescriptor) functionParent);
515 invokeOpcode = INVOKEVIRTUAL;
516 }
517 else if (functionParent instanceof ClassDescriptor) {
518
519 FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor);
520
521 ClassDescriptor currentOwner = (ClassDescriptor) functionParent;
522 ClassDescriptor declarationOwner = (ClassDescriptor) declarationFunctionDescriptor.getContainingDeclaration();
523
524 boolean originalIsInterface = isInterface(declarationOwner);
525 boolean currentIsInterface = isInterface(currentOwner);
526
527 boolean isAccessor = isAccessor(functionDescriptor);
528
529 ClassDescriptor receiver;
530 if (currentIsInterface && !originalIsInterface) {
531 receiver = declarationOwner;
532 }
533 else {
534 receiver = currentOwner;
535 }
536
537 // TODO: TYPE_PARAMETER is hack here
538
539 boolean isInterface = originalIsInterface && currentIsInterface;
540 Type type = mapType(receiver.getDefaultType(), JetTypeMapperMode.TYPE_PARAMETER);
541 owner = JvmClassName.byType(type);
542
543 ClassDescriptor declarationOwnerForDefault = (ClassDescriptor) findBaseDeclaration(functionDescriptor).getContainingDeclaration();
544 ownerForDefaultParam = JvmClassName.byType(mapType(declarationOwnerForDefault.getDefaultType(), JetTypeMapperMode.TYPE_PARAMETER));
545 ownerForDefaultImpl = JvmClassName.byInternalName(
546 ownerForDefaultParam.getInternalName() + (isInterface(declarationOwnerForDefault) ? JvmAbi.TRAIT_IMPL_SUFFIX : ""));
547 if (isInterface) {
548 invokeOpcode = superCall ? INVOKESTATIC : INVOKEINTERFACE;
549 }
550 else {
551 if (isAccessor) {
552 invokeOpcode = INVOKESTATIC;
553 }
554 else {
555 boolean isPrivateFunInvocation = isInsideClass && functionDescriptor.getVisibility() == Visibilities.PRIVATE;
556 invokeOpcode = superCall || isPrivateFunInvocation ? INVOKESPECIAL : INVOKEVIRTUAL;
557 }
558 }
559
560 if (isInterface && superCall) {
561 descriptor = mapSignature(functionDescriptor, false, OwnerKind.TRAIT_IMPL);
562 owner = JvmClassName.byInternalName(owner.getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
563 }
564 thisClass = JvmClassName.byType(mapType(receiver.getDefaultType()));
565 }
566 else {
567 throw new UnsupportedOperationException("unknown function parent");
568 }
569
570
571 Type receiverParameterType;
572 ReceiverParameterDescriptor receiverParameter = functionDescriptor.getOriginal().getReceiverParameter();
573 if (receiverParameter != null) {
574 receiverParameterType = mapType(receiverParameter.getType());
575 }
576 else {
577 receiverParameterType = null;
578 }
579 return new CallableMethod(
580 owner, ownerForDefaultImpl, ownerForDefaultParam, descriptor, invokeOpcode,
581 thisClass, receiverParameterType, null);
582 }
583
584 public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
585 return descriptor instanceof AccessorForFunctionDescriptor ||
586 descriptor instanceof AccessorForPropertyDescriptor ||
587 descriptor instanceof AccessorForPropertyDescriptor.Getter ||
588 descriptor instanceof AccessorForPropertyDescriptor.Setter;
589 }
590
591 @NotNull
592 private static FunctionDescriptor findAnyDeclaration(@NotNull FunctionDescriptor function) {
593 if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
594 return function;
595 }
596 return findBaseDeclaration(function);
597 }
598
599 @NotNull
600 private static FunctionDescriptor findBaseDeclaration(@NotNull FunctionDescriptor function) {
601 if (function.getOverriddenDescriptors().isEmpty()) {
602 return function;
603 }
604 else {
605 // TODO: prefer class to interface
606 return findBaseDeclaration(function.getOverriddenDescriptors().iterator().next());
607 }
608 }
609
610 @NotNull
611 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, boolean needGenericSignature, @NotNull OwnerKind kind) {
612 String name = f.getName().asString();
613 if (f instanceof PropertyAccessorDescriptor) {
614 boolean isGetter = f instanceof PropertyGetterDescriptor;
615 name = getPropertyAccessorName(((PropertyAccessorDescriptor) f).getCorrespondingProperty(), isGetter);
616 }
617 return mapSignature(name, f, needGenericSignature, kind);
618 }
619
620 @NotNull
621 public JvmMethodSignature mapSignature(@NotNull Name functionName, @NotNull FunctionDescriptor f) {
622 return mapSignature(functionName.asString(), f, false, OwnerKind.IMPLEMENTATION);
623 }
624
625 @NotNull
626 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f) {
627 return mapSignature(f.getName(), f);
628 }
629
630 @NotNull
631 private JvmMethodSignature mapSignature(
632 @NotNull String methodName,
633 @NotNull FunctionDescriptor f,
634 boolean needGenericSignature,
635 @NotNull OwnerKind kind
636 ) {
637 if (kind == OwnerKind.TRAIT_IMPL) {
638 needGenericSignature = false;
639 }
640
641 BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, needGenericSignature);
642
643 writeFormalTypeParameters(f.getTypeParameters(), signatureVisitor);
644
645 signatureVisitor.writeParametersStart();
646 writeThisIfNeeded(f, kind, signatureVisitor);
647 writeReceiverIfNeeded(f.getReceiverParameter(), signatureVisitor);
648
649 for (ValueParameterDescriptor parameter : f.getValueParameters()) {
650 writeParameter(signatureVisitor, parameter.getType());
651 }
652
653 signatureVisitor.writeParametersEnd();
654
655 if (f instanceof ConstructorDescriptor) {
656 signatureVisitor.writeVoidReturn();
657 }
658 else {
659 signatureVisitor.writeReturnType();
660 JetType returnType = f.getReturnType();
661 assert returnType != null : "Function " + f + " has no return type";
662 mapReturnType(returnType, signatureVisitor);
663 signatureVisitor.writeReturnTypeEnd();
664 }
665
666 return signatureVisitor.makeJvmMethodSignature(methodName);
667 }
668
669 @Nullable
670 public String mapFieldSignature(@NotNull JetType backingFieldType) {
671 BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE, true);
672 signatureVisitor.writeFieldTypeStart();
673 mapType(backingFieldType, signatureVisitor, JetTypeMapperMode.VALUE);
674 signatureVisitor.writeFieldTypeEnd();
675 return signatureVisitor.makeJavaGenericSignature();
676 }
677
678 private void writeThisIfNeeded(
679 @NotNull CallableMemberDescriptor descriptor,
680 @NotNull OwnerKind kind,
681 @NotNull BothSignatureWriter signatureVisitor
682 ) {
683 if (kind == OwnerKind.TRAIT_IMPL) {
684 ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
685 Type type = getTraitImplThisParameterType(containingDeclaration, this);
686
687 signatureVisitor.writeParameterType(JvmMethodParameterKind.THIS);
688 signatureVisitor.writeAsmType(type, false);
689 signatureVisitor.writeParameterTypeEnd();
690 }
691 else {
692 writeThisForAccessorIfNeeded(descriptor, signatureVisitor);
693 }
694 }
695
696 private void writeThisForAccessorIfNeeded(@NotNull CallableMemberDescriptor descriptor, @NotNull BothSignatureWriter signatureVisitor) {
697 if (isAccessor(descriptor) && descriptor.getExpectedThisObject() != null) {
698 signatureVisitor.writeParameterType(JvmMethodParameterKind.THIS);
699 mapType(((ClassifierDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), signatureVisitor, JetTypeMapperMode.VALUE);
700 signatureVisitor.writeParameterTypeEnd();
701 }
702 }
703
704
705 public void writeFormalTypeParameters(List<TypeParameterDescriptor> typeParameters, BothSignatureWriter signatureVisitor) {
706 if (signatureVisitor == null) {
707 return;
708 }
709
710 signatureVisitor.writeFormalTypeParametersStart();
711 for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
712 writeFormalTypeParameter(typeParameterDescriptor, signatureVisitor);
713 }
714 signatureVisitor.writeFormalTypeParametersEnd();
715 }
716
717 private void writeFormalTypeParameter(TypeParameterDescriptor typeParameterDescriptor, BothSignatureWriter signatureVisitor) {
718 signatureVisitor.writeFormalTypeParameter(typeParameterDescriptor.getName().asString(), typeParameterDescriptor.getVariance(),
719 typeParameterDescriptor.isReified());
720
721 classBound:
722 {
723 signatureVisitor.writeClassBound();
724
725 for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
726 if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
727 if (!isInterface(jetType)) {
728 mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
729 break classBound;
730 }
731 }
732 }
733
734 // "extends Object" is optional according to ClassFileFormat-Java5.pdf
735 // but javac complaints to signature:
736 // <P:>Ljava/lang/Object;
737 // TODO: avoid writing java/lang/Object if interface list is not empty
738 }
739 signatureVisitor.writeClassBoundEnd();
740
741 for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
742 if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
743 if (isInterface(jetType)) {
744 signatureVisitor.writeInterfaceBound();
745 mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
746 signatureVisitor.writeInterfaceBoundEnd();
747 }
748 }
749 if (jetType.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
750 signatureVisitor.writeInterfaceBound();
751 mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
752 signatureVisitor.writeInterfaceBoundEnd();
753 }
754 }
755
756 signatureVisitor.writeFormalTypeParameterEnd();
757 }
758
759
760 private void writeReceiverIfNeeded(@Nullable ReceiverParameterDescriptor receiver, BothSignatureWriter signatureWriter) {
761 if (receiver != null) {
762 signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER);
763 mapType(receiver.getType(), signatureWriter, JetTypeMapperMode.VALUE);
764 signatureWriter.writeParameterTypeEnd();
765 }
766 }
767
768 @NotNull
769 public static String getPropertyAccessorName(@NotNull PropertyDescriptor descriptor, boolean isGetter) {
770 DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration();
771 boolean isAnnotation = parentDescriptor instanceof ClassDescriptor &&
772 ((ClassDescriptor) parentDescriptor).getKind() == ClassKind.ANNOTATION_CLASS;
773 return isAnnotation ? descriptor.getName().asString() :
774 isGetter ? PropertyCodegen.getterName(descriptor.getName()) : PropertyCodegen.setterName(descriptor.getName());
775 }
776
777 @NotNull
778 public JvmPropertyAccessorSignature mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
779 // TODO: do not genClassOrObject generics if not needed
780 BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
781
782 writeFormalTypeParameters(descriptor.getTypeParameters(), signatureWriter);
783
784 signatureWriter.writeParametersStart();
785 writeThisIfNeeded(descriptor, kind, signatureWriter);
786 writeReceiverIfNeeded(descriptor.getReceiverParameter(), signatureWriter);
787 signatureWriter.writeParametersEnd();
788
789 signatureWriter.writeReturnType();
790 mapType(descriptor.getType(), signatureWriter, JetTypeMapperMode.VALUE, Variance.OUT_VARIANCE);
791 signatureWriter.writeReturnTypeEnd();
792
793 String name = getPropertyAccessorName(descriptor, true);
794 return signatureWriter.makeJvmPropertyAccessorSignature(name, true);
795 }
796
797
798 @NotNull
799 public JvmPropertyAccessorSignature mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
800 assert descriptor.isVar();
801
802 // TODO: generics signature is not always needed
803 BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
804
805 writeFormalTypeParameters(descriptor.getTypeParameters(), signatureWriter);
806
807 signatureWriter.writeParametersStart();
808 writeThisIfNeeded(descriptor, kind, signatureWriter);
809 writeReceiverIfNeeded(descriptor.getReceiverParameter(), signatureWriter);
810 writeParameter(signatureWriter, descriptor.getType());
811 signatureWriter.writeParametersEnd();
812
813 signatureWriter.writeVoidReturn();
814
815 String name = getPropertyAccessorName(descriptor, false);
816 return signatureWriter.makeJvmPropertyAccessorSignature(name, false);
817 }
818
819 private void writeParameter(@NotNull BothSignatureWriter signatureWriter, @NotNull JetType outType) {
820 signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
821 mapType(outType, signatureWriter, JetTypeMapperMode.VALUE);
822 signatureWriter.writeParameterTypeEnd();
823 }
824
825 @NotNull
826 public JvmMethodSignature mapConstructorSignature(@NotNull ConstructorDescriptor descriptor) {
827 return mapConstructorSignature(descriptor, bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration()));
828 }
829
830 @NotNull
831 public JvmMethodSignature mapConstructorSignature(@NotNull ConstructorDescriptor descriptor, @Nullable CalculatedClosure closure) {
832
833 BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
834
835 // constructor type parmeters are fake
836 writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), signatureWriter);
837
838 signatureWriter.writeParametersStart();
839
840 ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
841 ClassDescriptor captureThis = getExpectedThisObjectForConstructorCall(descriptor, closure);
842 if (captureThis != null) {
843 signatureWriter.writeParameterType(JvmMethodParameterKind.OUTER);
844 mapType(captureThis.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE);
845 signatureWriter.writeParameterTypeEnd();
846 }
847
848 ClassifierDescriptor captureReceiver = closure != null ? closure.getCaptureReceiver() : null;
849 if (captureReceiver != null) {
850 signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER);
851 mapType(captureReceiver.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE);
852 signatureWriter.writeParameterTypeEnd();
853 }
854
855 if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
856 signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_NAME);
857 mapType(KotlinBuiltIns.getInstance().getStringType(), signatureWriter, JetTypeMapperMode.VALUE);
858 signatureWriter.writeParameterTypeEnd();
859 signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_ORDINAL);
860 mapType(KotlinBuiltIns.getInstance().getIntType(), signatureWriter, JetTypeMapperMode.VALUE);
861 signatureWriter.writeParameterTypeEnd();
862 }
863
864 if (closure != null) {
865 for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) {
866 DeclarationDescriptor variableDescriptor = entry.getKey();
867 Type type = null;
868 if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) {
869 Type sharedVarType = getSharedVarType(variableDescriptor);
870 if (sharedVarType == null) {
871 sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType());
872 }
873 type = sharedVarType;
874 }
875 else if (isLocalNamedFun(variableDescriptor)) {
876 type = classNameForAnonymousClass(bindingContext, (FunctionDescriptor) variableDescriptor).getAsmType();
877 }
878
879 if (type != null) {
880 signatureWriter.writeParameterType(JvmMethodParameterKind.SHARED_VAR);
881 signatureWriter.writeAsmType(type, false);
882 signatureWriter.writeParameterTypeEnd();
883 }
884 }
885
886 JetDelegatorToSuperCall superCall = closure.getSuperCall();
887 if (superCall != null) {
888 DeclarationDescriptor superDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET,
889 superCall
890 .getCalleeExpression()
891 .getConstructorReferenceExpression());
892
893 if(superDescriptor instanceof ConstructorDescriptor) {
894 ConstructorDescriptor superConstructor = (ConstructorDescriptor) superDescriptor;
895
896 if (isObjectLiteral(bindingContext, descriptor.getContainingDeclaration())) {
897 List<JvmMethodParameterSignature> types = mapConstructorSignature(superConstructor).getKotlinParameterTypes();
898 if (types != null) {
899 for (JvmMethodParameterSignature type : types) {
900 signatureWriter.writeParameterType(JvmMethodParameterKind.SUPER_CALL_PARAM);
901 signatureWriter.writeAsmType(type.getAsmType(), false);
902 signatureWriter.writeParameterTypeEnd();
903 }
904 }
905 }
906 }
907 }
908 }
909
910 for (ValueParameterDescriptor parameter : descriptor.getOriginal().getValueParameters()) {
911 writeParameter(signatureWriter, parameter.getType());
912 }
913
914 signatureWriter.writeParametersEnd();
915
916 signatureWriter.writeVoidReturn();
917
918 return signatureWriter.makeJvmMethodSignature("<init>");
919 }
920
921 @NotNull
922 public JvmMethodSignature mapScriptSignature(@NotNull ScriptDescriptor script, @NotNull List<ScriptDescriptor> importedScripts) {
923 BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
924
925 writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), signatureWriter);
926
927 signatureWriter.writeParametersStart();
928
929 for (ScriptDescriptor importedScript : importedScripts) {
930 signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
931 ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_SCRIPT, importedScript);
932 assert descriptor != null;
933 mapType(descriptor.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE);
934 signatureWriter.writeParameterTypeEnd();
935 }
936
937 for (ValueParameterDescriptor valueParameter : script.getValueParameters()) {
938 writeParameter(signatureWriter, valueParameter.getType());
939 }
940
941 signatureWriter.writeParametersEnd();
942
943 signatureWriter.writeVoidReturn();
944
945 return signatureWriter.makeJvmMethodSignature("<init>");
946 }
947
948 @NotNull
949 public CallableMethod mapToCallableMethod(@NotNull ConstructorDescriptor descriptor) {
950 return mapToCallableMethod(descriptor, bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration()));
951 }
952
953 @NotNull
954 public CallableMethod mapToCallableMethod(@NotNull ConstructorDescriptor descriptor, @Nullable CalculatedClosure closure) {
955 JvmMethodSignature method = mapConstructorSignature(descriptor, closure);
956 JetType defaultType = descriptor.getContainingDeclaration().getDefaultType();
957 Type mapped = mapType(defaultType, JetTypeMapperMode.IMPL);
958 if (mapped.getSort() != Type.OBJECT) {
959 throw new IllegalStateException("type must have been mapped to object: " + defaultType + ", actual: " + mapped);
960 }
961 JvmClassName owner = JvmClassName.byType(mapped);
962 return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL, null, null, null);
963 }
964
965
966 private static boolean isGenericsArray(JetType type) {
967 return KotlinBuiltIns.getInstance().isArray(type) &&
968 type.getArguments().get(0).getType().getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor;
969 }
970
971 public Type getSharedVarType(DeclarationDescriptor descriptor) {
972 if (descriptor instanceof PropertyDescriptor) {
973 return StackValue
974 .sharedTypeForType(mapType(((PropertyDescriptor) descriptor).getReceiverParameter().getType()));
975 }
976 else if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
977 return classNameForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor).getAsmType();
978 }
979 else if (descriptor instanceof FunctionDescriptor) {
980 return StackValue
981 .sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType()));
982 }
983 else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) {
984 JetType outType = ((VariableDescriptor) descriptor).getType();
985 return StackValue.sharedTypeForType(mapType(outType));
986 }
987 return null;
988 }
989
990 @NotNull
991 public CallableMethod mapToFunctionInvokeCallableMethod(@NotNull FunctionDescriptor fd) {
992 JvmMethodSignature descriptor = erasedInvokeSignature(fd);
993 JvmClassName owner = getFunctionTraitClassName(fd);
994 Type receiverParameterType;
995 ReceiverParameterDescriptor receiverParameter = fd.getOriginal().getReceiverParameter();
996 if (receiverParameter != null) {
997 receiverParameterType = mapType(receiverParameter.getType());
998 }
999 else {
1000 receiverParameterType = null;
1001 }
1002 return new CallableMethod(owner, null, null, descriptor, INVOKEINTERFACE, owner, receiverParameterType, owner.getAsmType());
1003 }
1004
1005 @NotNull
1006 public Type expressionType(JetExpression expr) {
1007 JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expr);
1008 return asmTypeOrVoid(type);
1009 }
1010
1011 @NotNull
1012 private Type asmTypeOrVoid(@Nullable JetType type) {
1013 return type == null ? Type.VOID_TYPE : mapType(type);
1014 }
1015 }