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 org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
022 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
023 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
024 import org.jetbrains.jet.lang.resolve.name.FqName;
025 import org.jetbrains.jet.lang.types.*;
026 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
027 import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter;
028 import org.jetbrains.jet.rt.signature.JetSignatureVariance;
029 import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
030
031 import java.util.ArrayList;
032 import java.util.Collections;
033 import java.util.List;
034
035 public 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 }