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