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;
018
019 import com.google.common.collect.Maps;
020 import com.google.common.collect.Sets;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.asm4.Type;
024 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
025 import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
026 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
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.JetType;
030 import org.jetbrains.jet.lang.types.lang.PrimitiveType;
031
032 import java.util.Map;
033 import java.util.Set;
034
035 public class KotlinToJavaTypesMap extends JavaToKotlinClassMapBuilder {
036 private static KotlinToJavaTypesMap instance = null;
037
038 @NotNull
039 public static KotlinToJavaTypesMap getInstance() {
040 if (instance == null) {
041 instance = new KotlinToJavaTypesMap();
042 }
043 return instance;
044 }
045
046 private final Map<FqName, Type> asmTypes = Maps.newHashMap();
047 private final Map<FqName, Type> asmNullableTypes = Maps.newHashMap();
048 private final Set<String> mappedTypeNames = Sets.newHashSet();
049
050 private KotlinToJavaTypesMap() {
051 init();
052 initPrimitives();
053 }
054
055 private void initPrimitives() {
056 for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
057 FqName className = jvmPrimitiveType.getPrimitiveType().getClassName();
058
059 register(className, jvmPrimitiveType.getAsmType());
060 registerNullable(className, jvmPrimitiveType.getWrapper().getAsmType());
061 }
062 for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
063 PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
064 register(primitiveType.getArrayClassName(), jvmPrimitiveType.getAsmArrayType());
065 }
066 }
067
068 @Nullable
069 public Type getJavaAnalog(@NotNull JetType jetType) {
070 ClassifierDescriptor classifier = jetType.getConstructor().getDeclarationDescriptor();
071 assert classifier != null;
072 FqNameUnsafe className = DescriptorUtils.getFQName(classifier);
073 if (!className.isSafe()) return null;
074 FqName fqName = className.toSafe();
075 if (jetType.isNullable()) {
076 Type nullableType = asmNullableTypes.get(fqName);
077 if (nullableType != null) {
078 return nullableType;
079 }
080 }
081 return asmTypes.get(fqName);
082 }
083
084 @Override
085 protected void register(
086 @NotNull Class<?> javaClass,
087 @NotNull ClassDescriptor kotlinDescriptor,
088 @NotNull Direction direction
089 ) {
090 if (direction == Direction.BOTH || direction == Direction.KOTLIN_TO_JAVA) {
091 register(kotlinDescriptor, AsmTypeConstants.getType(javaClass));
092 }
093 }
094
095 @Override
096 protected void register(
097 @NotNull Class<?> javaClass,
098 @NotNull ClassDescriptor kotlinDescriptor,
099 @NotNull ClassDescriptor kotlinMutableDescriptor,
100 @NotNull Direction direction
101 ) {
102 if (direction == Direction.BOTH || direction == Direction.KOTLIN_TO_JAVA) {
103 register(javaClass, kotlinDescriptor);
104 register(javaClass, kotlinMutableDescriptor);
105 }
106 }
107
108 private void register(@NotNull ClassDescriptor kotlinDescriptor, @NotNull Type javaType) {
109 FqNameUnsafe fqName = DescriptorUtils.getFQName(kotlinDescriptor);
110 assert fqName.isSafe();
111 register(fqName.toSafe(), javaType);
112 }
113
114 private void register(@NotNull FqName fqName, @NotNull Type type) {
115 mappedTypeNames.add(type.getClassName());
116 asmTypes.put(fqName, type);
117 }
118
119 private void registerNullable(@NotNull FqName fqName, @NotNull Type nullableType) {
120 asmNullableTypes.put(fqName, nullableType);
121 }
122
123 public boolean isForceReal(@NotNull JvmClassName className) {
124 return JvmPrimitiveType.getByWrapperClass(className) != null
125 || mappedTypeNames.contains(className.getFqName().asString());
126 }
127 }