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 org.jetbrains.annotations.NotNull; 020import org.jetbrains.annotations.Nullable; 021import org.jetbrains.jet.lang.descriptors.ClassDescriptor; 022import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 023import org.jetbrains.jet.lang.resolve.DescriptorUtils; 024import org.jetbrains.jet.lang.resolve.name.FqName; 025import org.jetbrains.jet.lang.types.*; 026import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 027import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter; 028import org.jetbrains.jet.rt.signature.JetSignatureVariance; 029import org.jetbrains.jet.rt.signature.JetSignatureVisitor; 030 031import java.util.ArrayList; 032import java.util.Collections; 033import java.util.List; 034 035public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAdapter { 036 037 private final JavaSemanticServices javaSemanticServices; 038 private final JavaDescriptorResolver javaDescriptorResolver; 039 private final KotlinBuiltIns kotlinBuiltIns; 040 private final TypeVariableResolver typeVariableResolver; 041 042 public JetTypeJetSignatureReader(JavaSemanticServices javaSemanticServices, KotlinBuiltIns kotlinBuiltIns, TypeVariableResolver typeVariableResolver) { 043 this.javaSemanticServices = javaSemanticServices; 044 this.javaDescriptorResolver = javaSemanticServices.getDescriptorResolver(); 045 this.kotlinBuiltIns = kotlinBuiltIns; 046 this.typeVariableResolver = typeVariableResolver; 047 } 048 049 050 private JetType getPrimitiveType(char descriptor, boolean nullable) { 051 if (!nullable) { 052 for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { 053 if (jvmPrimitiveType.getJvmLetter() == descriptor) { 054 return KotlinBuiltIns.getInstance().getPrimitiveJetType(jvmPrimitiveType.getPrimitiveType()); 055 } 056 } 057 if (descriptor == 'V') { 058 return KotlinBuiltIns.getInstance().getUnitType(); 059 } 060 } 061 else { 062 for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { 063 if (jvmPrimitiveType.getJvmLetter() == descriptor) { 064 return KotlinBuiltIns.getInstance().getNullablePrimitiveJetType(jvmPrimitiveType.getPrimitiveType()); 065 } 066 } 067 if (descriptor == 'V') { 068 throw new IllegalStateException("incorrect signature: nullable void"); 069 } 070 } 071 throw new IllegalStateException("incorrect signature"); 072 } 073 074 @Override 075 public void visitBaseType(char descriptor, boolean nullable) { 076 done(getPrimitiveType(descriptor, nullable)); 077 } 078 079 080 private ClassDescriptor classDescriptor; 081 private JetType errorType; 082 private boolean nullable; 083 private List<TypeProjection> typeArguments; 084 085 @Override 086 public void visitClassType(String signatureName, boolean nullable, boolean forceReal) { 087 FqName fqName = JvmClassName.bySignatureName(signatureName).getFqName(); 088 089 enterClass(resolveClassDescriptorByFqName(fqName, forceReal), fqName.asString(), nullable); 090 } 091 092 private void enterClass(@Nullable ClassDescriptor classDescriptor, @NotNull String className, boolean nullable) { 093 this.classDescriptor = classDescriptor; 094 095 if (this.classDescriptor == null) { 096 // TODO: report in to trace 097 this.errorType = ErrorUtils.createErrorType("class not found by name: " + className); 098 } 099 this.nullable = nullable; 100 this.typeArguments = new ArrayList<TypeProjection>(); 101 } 102 103 @Nullable 104 private ClassDescriptor resolveClassDescriptorByFqName(FqName ourName, boolean forceReal) { 105 if (!forceReal) { 106 ClassDescriptor mappedDescriptor = JavaToKotlinClassMap.getInstance(). 107 mapKotlinClass(ourName, TypeUsage.MEMBER_SIGNATURE_INVARIANT); 108 if (mappedDescriptor != null) { 109 return mappedDescriptor; 110 } 111 } 112 113 return javaDescriptorResolver.resolveClass(ourName, DescriptorSearchRule.INCLUDE_KOTLIN); 114 } 115 116 @Override 117 public void visitInnerClassType(String signatureName, boolean nullable, boolean forceReal) { 118 JvmClassName jvmClassName = JvmClassName.bySignatureName(signatureName); 119 ClassDescriptor descriptor = resolveClassDescriptorByFqName(jvmClassName.getOuterClassFqName(), forceReal); 120 for (String innerClassName : jvmClassName.getInnerClassNameList()) { 121 descriptor = descriptor != null ? DescriptorUtils.getInnerClassByName(descriptor, innerClassName) : null; 122 } 123 enterClass(descriptor, signatureName, nullable); 124 } 125 126 private static Variance parseVariance(JetSignatureVariance variance) { 127 switch (variance) { 128 case INVARIANT: return Variance.INVARIANT; 129 case OUT: return Variance.OUT_VARIANCE; 130 case IN: return Variance.IN_VARIANCE; 131 default: throw new IllegalStateException(); 132 } 133 } 134 135 @Override 136 public JetSignatureVisitor visitTypeArgument(final JetSignatureVariance variance) { 137 return new JetTypeJetSignatureReader(javaSemanticServices, kotlinBuiltIns, typeVariableResolver) { 138 139 @Override 140 protected void done(@NotNull JetType jetType) { 141 typeArguments.add(new TypeProjection(parseVariance(variance), jetType)); 142 } 143 }; 144 } 145 146 @Override 147 public JetSignatureVisitor visitArrayType(final boolean nullable, final JetSignatureVariance wildcard) { 148 return new JetTypeJetSignatureReader(javaSemanticServices, kotlinBuiltIns, typeVariableResolver) { 149 @Override 150 public void visitBaseType(char descriptor, boolean nullable) { 151 JetType primitiveType = getPrimitiveType(descriptor, nullable); 152 JetType arrayType; 153 if (!nullable) { 154 arrayType = KotlinBuiltIns.getInstance().getPrimitiveArrayJetTypeByPrimitiveJetType(primitiveType); 155 } 156 else { 157 arrayType = TypeUtils.makeNullableAsSpecified(KotlinBuiltIns.getInstance().getArrayType(primitiveType), nullable); 158 } 159 JetTypeJetSignatureReader.this.done(arrayType); 160 } 161 162 @Override 163 protected void done(@NotNull JetType jetType) { 164 JetType arrayType = TypeUtils.makeNullableAsSpecified(KotlinBuiltIns.getInstance().getArrayType( 165 parseVariance(wildcard), jetType), nullable); 166 JetTypeJetSignatureReader.this.done(arrayType); 167 } 168 }; 169 } 170 171 @Override 172 public void visitTypeVariable(String name, boolean nullable) { 173 JetType r = TypeUtils.makeNullableAsSpecified(typeVariableResolver.getTypeVariable(name).getDefaultType(), nullable); 174 done(r); 175 } 176 177 @Override 178 public void visitEnd() { 179 if ((errorType != null) == (classDescriptor != null)) { 180 throw new IllegalStateException("must initialize either errorType or classDescriptor"); 181 } 182 JetType jetType; 183 if (errorType != null) { 184 jetType = errorType; 185 } 186 else { 187 jetType = new JetTypeImpl( 188 Collections.<AnnotationDescriptor>emptyList(), 189 classDescriptor.getTypeConstructor(), 190 nullable, 191 typeArguments, 192 classDescriptor.getMemberScope(typeArguments)); 193 } 194 done(jetType); 195 } 196 197 protected abstract void done(@NotNull JetType jetType); 198}