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.lang.resolve.java.mapping;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.asm4.Type;
022 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
023 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
024 import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
025 import org.jetbrains.jet.lang.resolve.java.JvmClassName;
026 import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
027 import org.jetbrains.jet.lang.resolve.name.FqName;
028 import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
029 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
030 import org.jetbrains.jet.lang.types.lang.PrimitiveType;
031
032 import java.util.HashMap;
033 import java.util.Map;
034
035 import static org.jetbrains.jet.lang.resolve.java.mapping.PrimitiveTypesUtil.asmTypeForPrimitive;
036
037 public class KotlinToJavaTypesMap extends JavaToKotlinClassMapBuilder {
038 private static KotlinToJavaTypesMap instance = null;
039
040 @NotNull
041 public static KotlinToJavaTypesMap getInstance() {
042 if (instance == null) {
043 instance = new KotlinToJavaTypesMap();
044 }
045 return instance;
046 }
047
048 private final Map<FqName, Type> asmTypes = new HashMap<FqName, Type>();
049 private final Map<FqName, Type> asmNullableTypes = new HashMap<FqName, Type>();
050 private final Map<FqName, FqName> kotlinToJavaFqName = new HashMap<FqName, FqName>();
051
052 private KotlinToJavaTypesMap() {
053 init();
054 initPrimitives();
055 }
056
057 private void initPrimitives() {
058 FqName builtInsFqName = KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME;
059 for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
060 PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
061 Type asmType = asmTypeForPrimitive(jvmPrimitiveType);
062 FqName fqName = builtInsFqName.child(primitiveType.getTypeName());
063
064 register(fqName, asmType);
065
066 FqName wrapperFqName = jvmPrimitiveType.getWrapperFqName();
067 registerNullable(fqName, Type.getObjectType(JvmClassName.byFqNameWithoutInnerClasses(wrapperFqName).getInternalName()));
068 registerFqName(fqName, wrapperFqName);
069
070 register(builtInsFqName.child(primitiveType.getArrayTypeName()), Type.getType("[" + asmType.getDescriptor()));
071 }
072 }
073
074 @Nullable
075 public Type getJavaAnalog(@NotNull FqName fqName, boolean isNullable) {
076 if (isNullable) {
077 Type nullableType = asmNullableTypes.get(fqName);
078 if (nullableType != null) {
079 return nullableType;
080 }
081 }
082 return asmTypes.get(fqName);
083 }
084
085 /**
086 * E.g.
087 * jet.Throwable -> java.lang.Throwable
088 * jet.Deprecated -> java.lang.annotation.Deprecated
089 * jet.Int -> java.lang.Integer
090 * jet.IntArray -> null
091 */
092 @Nullable
093 public FqName getKotlinToJavaFqName(@NotNull FqName fqName) {
094 return kotlinToJavaFqName.get(fqName);
095 }
096
097 @Override
098 protected void register(@NotNull Class<?> javaClass, @NotNull ClassDescriptor kotlinDescriptor, @NotNull Direction direction) {
099 if (direction == Direction.BOTH || direction == Direction.KOTLIN_TO_JAVA) {
100 FqNameUnsafe fqNameUnsafe = DescriptorUtils.getFQName(kotlinDescriptor);
101 assert fqNameUnsafe.isSafe() : "FQ name of a mapped class should be safe: " + fqNameUnsafe;
102 FqName fqName = fqNameUnsafe.toSafe();
103 register(fqName, AsmTypeConstants.getType(javaClass));
104 registerFqName(fqName, new FqName(javaClass.getCanonicalName()));
105 }
106 }
107
108 @Override
109 protected void register(
110 @NotNull Class<?> javaClass,
111 @NotNull ClassDescriptor kotlinDescriptor,
112 @NotNull ClassDescriptor kotlinMutableDescriptor,
113 @NotNull Direction direction
114 ) {
115 if (direction == Direction.BOTH || direction == Direction.KOTLIN_TO_JAVA) {
116 register(javaClass, kotlinDescriptor);
117 register(javaClass, kotlinMutableDescriptor);
118 }
119 }
120
121 private void register(@NotNull FqName fqName, @NotNull Type type) {
122 asmTypes.put(fqName, type);
123 }
124
125 private void registerNullable(@NotNull FqName fqName, @NotNull Type nullableType) {
126 asmNullableTypes.put(fqName, nullableType);
127 }
128
129 private void registerFqName(@NotNull FqName kotlinFqName, @NotNull FqName javaFqName) {
130 kotlinToJavaFqName.put(kotlinFqName, javaFqName);
131 }
132 }