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 017package org.jetbrains.jet.lang.resolve.java; 018 019import com.google.common.collect.Maps; 020import com.google.common.collect.Sets; 021import org.jetbrains.annotations.NotNull; 022import org.jetbrains.annotations.Nullable; 023import org.jetbrains.asm4.Type; 024import org.jetbrains.jet.lang.descriptors.ClassDescriptor; 025import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; 026import org.jetbrains.jet.lang.resolve.DescriptorUtils; 027import org.jetbrains.jet.lang.resolve.name.FqName; 028import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; 029import org.jetbrains.jet.lang.types.JetType; 030import org.jetbrains.jet.lang.types.lang.PrimitiveType; 031 032import java.util.Map; 033import java.util.Set; 034 035public 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}