All the special types are now handled by SpecialTypes class
- this concept used to be called "known types" before
This commit is contained in:
@@ -217,7 +217,7 @@ public class CodegenContexts {
|
|||||||
|
|
||||||
final Type type = enclosingClassType(typeMapper);
|
final Type type = enclosingClassType(typeMapper);
|
||||||
outerExpression = type != null
|
outerExpression = type != null
|
||||||
? StackValue.field(type, typeMapper.getClassFQName(contextDescriptor), "this$0", false)
|
? StackValue.field(type, typeMapper.getJvmClassName(contextDescriptor), "this$0", false)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,11 +83,78 @@ public class JetTypeMapper {
|
|||||||
public static final Type TYPE_FUNCTION0 = Type.getObjectType("jet/Function0");
|
public static final Type TYPE_FUNCTION0 = Type.getObjectType("jet/Function0");
|
||||||
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
|
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
|
||||||
|
|
||||||
|
public static class SpecialTypes {
|
||||||
|
private static final class SpecialTypeKey {
|
||||||
|
@NotNull
|
||||||
|
private final FqNameUnsafe className;
|
||||||
|
private final boolean nullable;
|
||||||
|
|
||||||
|
private SpecialTypeKey(@NotNull FqNameUnsafe className, boolean nullable) {
|
||||||
|
this.className = className;
|
||||||
|
this.nullable = nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
SpecialTypeKey that = (SpecialTypeKey) o;
|
||||||
|
|
||||||
|
if (nullable != that.nullable) return false;
|
||||||
|
if (!className.equals(that.className)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = className.hashCode();
|
||||||
|
result = 31 * result + (nullable ? 1 : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Map<SpecialTypeKey, Type> asmTypes = Maps.newHashMap();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Type get(@NotNull JetType type) {
|
||||||
|
ClassifierDescriptor classifier = type.getConstructor().getDeclarationDescriptor();
|
||||||
|
return asmTypes.get(new SpecialTypeKey(DescriptorUtils.getFQName(classifier), type.isNullable()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void register(@NotNull ClassName className, @NotNull Type nonNullType, @NotNull Type nullableType) {
|
||||||
|
asmTypes.put(new SpecialTypeKey(className.getFqName().toUnsafe(), true), nullableType);
|
||||||
|
asmTypes.put(new SpecialTypeKey(className.getFqName().toUnsafe(), false), nonNullType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
register(JetStandardLibraryNames.NOTHING, TYPE_NOTHING, TYPE_NOTHING);
|
||||||
|
|
||||||
|
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
|
||||||
|
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
|
||||||
|
register(primitiveType.getClassName(), jvmPrimitiveType.getAsmType(), jvmPrimitiveType.getWrapper().getAsmType());
|
||||||
|
}
|
||||||
|
|
||||||
|
register(JetStandardLibraryNames.NUMBER, JL_NUMBER_TYPE, JL_NUMBER_TYPE);
|
||||||
|
register(JetStandardLibraryNames.STRING, JL_STRING_TYPE, JL_STRING_TYPE);
|
||||||
|
register(JetStandardLibraryNames.CHAR_SEQUENCE, JL_CHAR_SEQUENCE_TYPE, JL_CHAR_SEQUENCE_TYPE);
|
||||||
|
register(JetStandardLibraryNames.THROWABLE, TYPE_THROWABLE, TYPE_THROWABLE);
|
||||||
|
register(JetStandardLibraryNames.COMPARABLE, JL_COMPARABLE_TYPE, JL_COMPARABLE_TYPE);
|
||||||
|
|
||||||
|
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
|
||||||
|
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
|
||||||
|
register(primitiveType.getArrayClassName(), jvmPrimitiveType.getAsmArrayType(), jvmPrimitiveType.getAsmArrayType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public BindingContext bindingContext;
|
public BindingContext bindingContext;
|
||||||
private ClosureAnnotator closureAnnotator;
|
private ClosureAnnotator closureAnnotator;
|
||||||
private boolean mapBuiltinsToJava;
|
private boolean mapBuiltinsToJava;
|
||||||
private ClassBuilderMode classBuilderMode;
|
private ClassBuilderMode classBuilderMode;
|
||||||
|
private final SpecialTypes specialTypes = new SpecialTypes();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public void setBindingContext(BindingContext bindingContext) {
|
public void setBindingContext(BindingContext bindingContext) {
|
||||||
@@ -111,12 +178,9 @@ public class JetTypeMapper {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
initKnownTypes();
|
specialTypes.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public boolean hasThis0(ClassDescriptor classDescriptor) {
|
public boolean hasThis0(ClassDescriptor classDescriptor) {
|
||||||
return closureAnnotator.hasThis0(classDescriptor);
|
return closureAnnotator.hasThis0(classDescriptor);
|
||||||
}
|
}
|
||||||
@@ -125,40 +189,6 @@ public class JetTypeMapper {
|
|||||||
return closureAnnotator;
|
return closureAnnotator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class KnownTypeKey {
|
|
||||||
@NotNull
|
|
||||||
private final FqNameUnsafe className;
|
|
||||||
private final boolean nullable;
|
|
||||||
|
|
||||||
private KnownTypeKey(@NotNull FqNameUnsafe className, boolean nullable) {
|
|
||||||
this.className = className;
|
|
||||||
this.nullable = nullable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
|
|
||||||
KnownTypeKey that = (KnownTypeKey) o;
|
|
||||||
|
|
||||||
if (nullable != that.nullable) return false;
|
|
||||||
if (!className.equals(that.className)) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = className.hashCode();
|
|
||||||
result = 31 * result + (nullable ? 1 : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final HashMap<KnownTypeKey, Type> knowTypes = Maps.newHashMap();
|
|
||||||
|
|
||||||
|
|
||||||
public static boolean isIntPrimitive(Type type) {
|
public static boolean isIntPrimitive(Type type) {
|
||||||
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE;
|
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE;
|
||||||
}
|
}
|
||||||
@@ -308,17 +338,12 @@ public class JetTypeMapper {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JvmClassName getClassFQName(ClassDescriptor classDescriptor) {
|
public JvmClassName getJvmClassName(ClassDescriptor classDescriptor) {
|
||||||
return JvmClassName.byInternalName(getFQName(classDescriptor));
|
return JvmClassName.byInternalName(getJvmInternalFQName(classDescriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Internal name
|
|
||||||
*
|
|
||||||
* @see DescriptorUtils#getFQName(DeclarationDescriptor)
|
|
||||||
*/
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private String getFQName(@NotNull DeclarationDescriptor descriptor) {
|
private String getJvmInternalFQName(@NotNull DeclarationDescriptor descriptor) {
|
||||||
descriptor = descriptor.getOriginal();
|
descriptor = descriptor.getOriginal();
|
||||||
|
|
||||||
if (descriptor instanceof FunctionDescriptor) {
|
if (descriptor instanceof FunctionDescriptor) {
|
||||||
@@ -339,15 +364,15 @@ public class JetTypeMapper {
|
|||||||
if (klass.getContainingDeclaration() instanceof ClassDescriptor) {
|
if (klass.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||||
ClassDescriptor containingKlass = (ClassDescriptor) klass.getContainingDeclaration();
|
ClassDescriptor containingKlass = (ClassDescriptor) klass.getContainingDeclaration();
|
||||||
if (containingKlass.getKind() == ClassKind.ENUM_CLASS) {
|
if (containingKlass.getKind() == ClassKind.ENUM_CLASS) {
|
||||||
return getFQName(containingKlass);
|
return getJvmInternalFQName(containingKlass);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return getFQName(containingKlass) + JvmAbi.CLASS_OBJECT_SUFFIX;
|
return getJvmInternalFQName(containingKlass) + JvmAbi.CLASS_OBJECT_SUFFIX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (klass.getKind() == ClassKind.ENUM_ENTRY) {
|
else if (klass.getKind() == ClassKind.ENUM_ENTRY) {
|
||||||
return getFQName(klass.getContainingDeclaration());
|
return getJvmInternalFQName(klass.getContainingDeclaration());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +390,7 @@ public class JetTypeMapper {
|
|||||||
return className.getInternalName();
|
return className.getInternalName();
|
||||||
}
|
}
|
||||||
|
|
||||||
String baseName = getFQName(container);
|
String baseName = getJvmInternalFQName(container);
|
||||||
if (!baseName.isEmpty()) {
|
if (!baseName.isEmpty()) {
|
||||||
return baseName + (container instanceof NamespaceDescriptor ? "/" : "$") + name.getIdentifier();
|
return baseName + (container instanceof NamespaceDescriptor ? "/" : "$") + name.getIdentifier();
|
||||||
}
|
}
|
||||||
@@ -385,17 +410,16 @@ public class JetTypeMapper {
|
|||||||
|
|
||||||
if (mapBuiltinsToJava) {
|
if (mapBuiltinsToJava) {
|
||||||
if (classifier instanceof ClassDescriptor) {
|
if (classifier instanceof ClassDescriptor) {
|
||||||
KnownTypeKey key = new KnownTypeKey(DescriptorUtils.getFQName(classifier), jetType.isNullable());
|
known = specialTypes.get(jetType);
|
||||||
known = knowTypes.get(key);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (known != null) {
|
if (known != null) {
|
||||||
if (kind == MapTypeMode.VALUE) {
|
if (kind == MapTypeMode.VALUE) {
|
||||||
return mapKnownAsmType(jetType, known, signatureVisitor, false);
|
return mapKnownAsmType(jetType, known, signatureVisitor);
|
||||||
}
|
}
|
||||||
else if (kind == MapTypeMode.TYPE_PARAMETER) {
|
else if (kind == MapTypeMode.TYPE_PARAMETER) {
|
||||||
return mapKnownAsmType(jetType, known, signatureVisitor, true);
|
return mapKnownAsmType(jetType, boxType(known), signatureVisitor);
|
||||||
}
|
}
|
||||||
else if (kind == MapTypeMode.TRAIT_IMPL) {
|
else if (kind == MapTypeMode.TRAIT_IMPL) {
|
||||||
throw new IllegalStateException("TRAIT_IMPL is not possible for " + jetType);
|
throw new IllegalStateException("TRAIT_IMPL is not possible for " + jetType);
|
||||||
@@ -428,7 +452,7 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
Type asmType = Type.getObjectType("error/NonExistentClass");
|
Type asmType = Type.getObjectType("error/NonExistentClass");
|
||||||
if (signatureVisitor != null) {
|
if (signatureVisitor != null) {
|
||||||
visitAsmType(signatureVisitor, asmType, true);
|
writeSimpleType(signatureVisitor, asmType, true);
|
||||||
}
|
}
|
||||||
checkValidType(asmType);
|
checkValidType(asmType);
|
||||||
return asmType;
|
return asmType;
|
||||||
@@ -461,7 +485,7 @@ public class JetTypeMapper {
|
|||||||
|
|
||||||
if (JetStandardClasses.getAny().equals(descriptor)) {
|
if (JetStandardClasses.getAny().equals(descriptor)) {
|
||||||
if (signatureVisitor != null) {
|
if (signatureVisitor != null) {
|
||||||
visitAsmType(signatureVisitor, TYPE_OBJECT, jetType.isNullable());
|
writeSimpleType(signatureVisitor, TYPE_OBJECT, jetType.isNullable());
|
||||||
}
|
}
|
||||||
checkValidType(TYPE_OBJECT);
|
checkValidType(TYPE_OBJECT);
|
||||||
return TYPE_OBJECT;
|
return TYPE_OBJECT;
|
||||||
@@ -469,33 +493,12 @@ public class JetTypeMapper {
|
|||||||
|
|
||||||
if (descriptor instanceof ClassDescriptor) {
|
if (descriptor instanceof ClassDescriptor) {
|
||||||
|
|
||||||
Type asmType;
|
|
||||||
boolean forceReal;
|
|
||||||
|
|
||||||
if (JetStandardLibraryNames.COMPARABLE.is((ClassDescriptor) descriptor) && mapBuiltinsToJava) {
|
JvmClassName name = getJvmClassName((ClassDescriptor) descriptor);
|
||||||
if (jetType.getArguments().size() != 1) {
|
Type asmType = Type.getObjectType(name.getInternalName() + (kind == MapTypeMode.TRAIT_IMPL ? JvmAbi.TRAIT_IMPL_SUFFIX : ""));
|
||||||
throw new UnsupportedOperationException("Comparable must have one type argument");
|
boolean forceReal = isForceReal(name);
|
||||||
}
|
|
||||||
|
|
||||||
asmType = JL_COMPARABLE_TYPE;
|
writeGenericType(jetType, signatureVisitor, asmType, forceReal);
|
||||||
forceReal = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
JvmClassName name = getClassFQName((ClassDescriptor) descriptor);
|
|
||||||
asmType = Type.getObjectType(name.getInternalName() + (kind == MapTypeMode.TRAIT_IMPL ? JvmAbi.TRAIT_IMPL_SUFFIX : ""));
|
|
||||||
forceReal = isForceReal(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signatureVisitor != null) {
|
|
||||||
signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable(), forceReal);
|
|
||||||
for (TypeProjection proj : jetType.getArguments()) {
|
|
||||||
// TODO: +-
|
|
||||||
signatureVisitor.writeTypeArgument(proj.getProjectionKind());
|
|
||||||
mapType(proj.getType(), signatureVisitor, MapTypeMode.TYPE_PARAMETER);
|
|
||||||
signatureVisitor.writeTypeArgumentEnd();
|
|
||||||
}
|
|
||||||
signatureVisitor.writeClassEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
checkValidType(asmType);
|
checkValidType(asmType);
|
||||||
return asmType;
|
return asmType;
|
||||||
@@ -516,25 +519,33 @@ public class JetTypeMapper {
|
|||||||
throw new UnsupportedOperationException("Unknown type " + jetType);
|
throw new UnsupportedOperationException("Unknown type " + jetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable BothSignatureWriter signatureVisitor, boolean boxPrimitive) {
|
private void writeGenericType(JetType jetType, BothSignatureWriter signatureVisitor, Type asmType, boolean forceReal) {
|
||||||
if (boxPrimitive) {
|
if (signatureVisitor != null) {
|
||||||
Type boxed = boxType(asmType);
|
signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable(), forceReal);
|
||||||
if (signatureVisitor != null) {
|
for (TypeProjection proj : jetType.getArguments()) {
|
||||||
visitAsmType(signatureVisitor, boxed, jetType.isNullable());
|
// TODO: +-
|
||||||
|
signatureVisitor.writeTypeArgument(proj.getProjectionKind());
|
||||||
|
mapType(proj.getType(), signatureVisitor, MapTypeMode.TYPE_PARAMETER);
|
||||||
|
signatureVisitor.writeTypeArgumentEnd();
|
||||||
}
|
}
|
||||||
checkValidType(boxed);
|
signatureVisitor.writeClassEnd();
|
||||||
return boxed;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (signatureVisitor != null) {
|
|
||||||
visitAsmType(signatureVisitor, asmType, jetType.isNullable());
|
|
||||||
}
|
|
||||||
checkValidType(asmType);
|
|
||||||
return asmType;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void visitAsmType(BothSignatureWriter visitor, Type asmType, boolean nullable) {
|
private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable BothSignatureWriter signatureVisitor) {
|
||||||
|
if (signatureVisitor != null) {
|
||||||
|
if (jetType.getArguments().isEmpty()) {
|
||||||
|
writeSimpleType(signatureVisitor, asmType, jetType.isNullable());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
writeGenericType(jetType, signatureVisitor, asmType, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkValidType(asmType);
|
||||||
|
return asmType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeSimpleType(BothSignatureWriter visitor, Type asmType, boolean nullable) {
|
||||||
visitor.writeAsmType(asmType, nullable);
|
visitor.writeAsmType(asmType, nullable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1029,30 +1040,6 @@ public class JetTypeMapper {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerKnownType(@NotNull ClassName className, @NotNull Type nonNullType, @NotNull Type nullableType) {
|
|
||||||
knowTypes.put(new KnownTypeKey(className.getFqName().toUnsafe(), true), nullableType);
|
|
||||||
knowTypes.put(new KnownTypeKey(className.getFqName().toUnsafe(), false), nonNullType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initKnownTypes() {
|
|
||||||
registerKnownType(JetStandardLibraryNames.NOTHING, TYPE_NOTHING, TYPE_NOTHING);
|
|
||||||
|
|
||||||
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
|
|
||||||
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
|
|
||||||
registerKnownType(primitiveType.getClassName(), jvmPrimitiveType.getAsmType(), jvmPrimitiveType.getWrapper().getAsmType());
|
|
||||||
}
|
|
||||||
|
|
||||||
registerKnownType(JetStandardLibraryNames.NUMBER, JL_NUMBER_TYPE, JL_NUMBER_TYPE);
|
|
||||||
registerKnownType(JetStandardLibraryNames.STRING, JL_STRING_TYPE, JL_STRING_TYPE);
|
|
||||||
registerKnownType(JetStandardLibraryNames.CHAR_SEQUENCE, JL_CHAR_SEQUENCE_TYPE, JL_CHAR_SEQUENCE_TYPE);
|
|
||||||
registerKnownType(JetStandardLibraryNames.THROWABLE, TYPE_THROWABLE, TYPE_THROWABLE);
|
|
||||||
|
|
||||||
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
|
|
||||||
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
|
|
||||||
registerKnownType(primitiveType.getArrayClassName(), jvmPrimitiveType.getAsmArrayType(), jvmPrimitiveType.getAsmArrayType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isForceReal(JvmClassName className) {
|
private static boolean isForceReal(JvmClassName className) {
|
||||||
return JvmPrimitiveType.getByWrapperClass(className) != null
|
return JvmPrimitiveType.getByWrapperClass(className) != null
|
||||||
|| className.getFqName().getFqName().equals("java.lang.String")
|
|| className.getFqName().getFqName().equals("java.lang.String")
|
||||||
|
|||||||
Reference in New Issue
Block a user