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.resolver;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
021 import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
022 import org.jetbrains.jet.lang.resolve.java.JvmAbi;
023 import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
024 import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifier;
025 import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifierType;
026 import org.jetbrains.jet.lang.resolve.name.FqName;
027 import org.jetbrains.jet.lang.types.ErrorUtils;
028 import org.jetbrains.jet.lang.types.JetType;
029 import org.jetbrains.jet.lang.types.TypeUtils;
030 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
031
032 import javax.inject.Inject;
033 import java.util.ArrayList;
034 import java.util.Collection;
035 import java.util.Collections;
036 import java.util.List;
037
038 import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES;
039
040 public final class JavaSupertypeResolver {
041 public static final FqName OBJECT_FQ_NAME = new FqName("java.lang.Object");
042
043 private JavaTypeTransformer typeTransformer;
044 private JavaClassResolver classResolver;
045
046 @Inject
047 public void setTypeTransformer(JavaTypeTransformer typeTransformer) {
048 this.typeTransformer = typeTransformer;
049 }
050
051 @Inject
052 public void setClassResolver(JavaClassResolver classResolver) {
053 this.classResolver = classResolver;
054 }
055
056 @NotNull
057 public Collection<JetType> getSupertypes(
058 @NotNull ClassDescriptor classDescriptor,
059 @NotNull JavaClass javaClass,
060 @NotNull List<TypeParameterDescriptor> typeParameters
061 ) {
062 TypeVariableResolver typeVariableResolver = new TypeVariableResolverImpl(typeParameters, classDescriptor);
063
064 List<JetType> result = transformSupertypeList(javaClass.getSupertypes(), typeVariableResolver);
065
066 return result.isEmpty() ? Collections.singletonList(getDefaultSupertype(javaClass)) : result;
067 }
068
069 @NotNull
070 private JetType getDefaultSupertype(@NotNull JavaClass javaClass) {
071 if (OBJECT_FQ_NAME.equals(javaClass.getFqName()) || javaClass.isAnnotationType()) {
072 return KotlinBuiltIns.getInstance().getAnyType();
073 }
074 else {
075 ClassDescriptor object = classResolver.resolveClass(OBJECT_FQ_NAME, IGNORE_KOTLIN_SOURCES);
076 if (object != null) {
077 return object.getDefaultType();
078 }
079 else {
080 //TODO: hack here
081 return KotlinBuiltIns.getInstance().getAnyType();
082 // throw new IllegalStateException("Could not resolve java.lang.Object");
083 }
084 }
085 }
086
087 @NotNull
088 private List<JetType> transformSupertypeList(
089 @NotNull Collection<JavaClassifierType> supertypes,
090 @NotNull TypeVariableResolver typeVariableResolver
091 ) {
092 List<JetType> result = new ArrayList<JetType>(supertypes.size());
093 for (JavaClassifierType type : supertypes) {
094 JavaClassifier resolved = type.getClassifier();
095 if (resolved != null) {
096 assert resolved instanceof JavaClass : "Supertype should be a class: " + resolved;
097 FqName fqName = ((JavaClass) resolved).getFqName();
098 assert fqName != null : "Unresolved supertype: " + resolved;
099 if (JvmAbi.JET_OBJECT.getFqName().equals(fqName)) {
100 continue;
101 }
102 }
103
104 JetType transformed = typeTransformer.transformToType(type, TypeUsage.SUPERTYPE, typeVariableResolver);
105 if (ErrorUtils.isErrorType(transformed)) {
106 // TODO: report INCOMPLETE_HIERARCHY
107 }
108 else {
109 result.add(TypeUtils.makeNotNullable(transformed));
110 }
111 }
112 return result;
113 }
114 }