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