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 com.intellij.psi.PsiClass;
020    import com.intellij.psi.PsiClassType;
021    import jet.typeinfo.TypeInfoVariance;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
025    import org.jetbrains.jet.lang.descriptors.ClassKind;
026    import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
027    import org.jetbrains.jet.lang.resolve.BindingContext;
028    import org.jetbrains.jet.lang.resolve.BindingTrace;
029    import org.jetbrains.jet.lang.resolve.java.*;
030    import org.jetbrains.jet.lang.resolve.java.provider.ClassPsiDeclarationProvider;
031    import org.jetbrains.jet.lang.resolve.java.wrapper.PsiClassWrapper;
032    import org.jetbrains.jet.lang.types.ErrorUtils;
033    import org.jetbrains.jet.lang.types.JetType;
034    import org.jetbrains.jet.lang.types.TypeUtils;
035    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
036    import org.jetbrains.jet.rt.signature.JetSignatureAdapter;
037    import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter;
038    import org.jetbrains.jet.rt.signature.JetSignatureReader;
039    import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
040    
041    import javax.inject.Inject;
042    import java.util.ArrayList;
043    import java.util.Collection;
044    import java.util.List;
045    
046    import static org.jetbrains.jet.lang.resolve.java.provider.DeclarationOrigin.KOTLIN;
047    
048    public final class JavaSupertypeResolver {
049    
050        private BindingTrace trace;
051        private JavaSemanticServices semanticServices;
052        private JavaTypeTransformer typeTransformer;
053        private JavaClassResolver classResolver;
054    
055        @Inject
056        public void setTrace(BindingTrace trace) {
057            this.trace = trace;
058        }
059    
060        @Inject
061        public void setSemanticServices(JavaSemanticServices semanticServices) {
062            this.semanticServices = semanticServices;
063        }
064    
065        @Inject
066        public void setTypeTransformer(JavaTypeTransformer typeTransformer) {
067            this.typeTransformer = typeTransformer;
068        }
069    
070        @Inject
071        public void setClassResolver(JavaClassResolver classResolver) {
072            this.classResolver = classResolver;
073        }
074    
075        public Collection<JetType> getSupertypes(
076                @NotNull ClassDescriptor classDescriptor,
077                @NotNull PsiClassWrapper psiClass,
078                @NotNull ClassPsiDeclarationProvider classData,
079                @NotNull List<TypeParameterDescriptor> typeParameters
080        ) {
081    
082            List<JetType> result = new ArrayList<JetType>();
083    
084            String context = "class " + psiClass.getQualifiedName();
085    
086            if (psiClass.getJetClass().signature().length() > 0) {
087                readSuperTypes(psiClass, typeParameters, classDescriptor, result, context);
088            }
089            else {
090                TypeVariableResolver typeVariableResolverForSupertypes =
091                        TypeVariableResolvers.typeVariableResolverFromTypeParameters(typeParameters, classDescriptor, context);
092                transformSupertypeList(result, psiClass.getPsiClass().getExtendsListTypes(), typeVariableResolverForSupertypes);
093                transformSupertypeList(result, psiClass.getPsiClass().getImplementsListTypes(), typeVariableResolverForSupertypes);
094            }
095    
096            reportIncompleteHierarchyForErrorTypes(classDescriptor, result);
097    
098            if (result.isEmpty()) {
099                addBaseClass(psiClass, classData, classDescriptor, result);
100            }
101            return result;
102        }
103    
104        private void readSuperTypes(
105                PsiClassWrapper psiClass,
106                List<TypeParameterDescriptor> typeParameters,
107                ClassDescriptor classDescriptor,
108                final List<JetType> result,
109                String context
110        ) {
111            final TypeVariableResolver typeVariableResolver =
112                    TypeVariableResolvers.typeVariableResolverFromTypeParameters(typeParameters, classDescriptor, context);
113    
114            new JetSignatureReader(psiClass.getJetClass().signature()).accept(new JetSignatureExceptionsAdapter() {
115                @Override
116                public JetSignatureVisitor visitFormalTypeParameter(String name, TypeInfoVariance variance, boolean reified) {
117                    // TODO: collect
118                    return new JetSignatureAdapter();
119                }
120    
121                @Override
122                public JetSignatureVisitor visitSuperclass() {
123                    return new JetTypeJetSignatureReader(semanticServices, KotlinBuiltIns.getInstance(),
124                                                         typeVariableResolver) {
125                        @Override
126                        protected void done(@NotNull JetType jetType) {
127                            if (!jetType.equals(KotlinBuiltIns.getInstance().getAnyType())) {
128                                result.add(jetType);
129                            }
130                        }
131                    };
132                }
133    
134                @Override
135                public JetSignatureVisitor visitInterface() {
136                    return visitSuperclass();
137                }
138            });
139        }
140    
141        private void addBaseClass(
142                @NotNull PsiClassWrapper psiClass,
143                @NotNull ClassPsiDeclarationProvider classData,
144                @NotNull ClassDescriptor classDescriptor,
145                @NotNull List<JetType> result
146        ) {
147            if (classData.getDeclarationOrigin() == KOTLIN
148                || DescriptorResolverUtils.OBJECT_FQ_NAME.equalsTo(psiClass.getQualifiedName())
149                // TODO: annotations
150                || classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) {
151                result.add(KotlinBuiltIns.getInstance().getAnyType());
152            }
153            else {
154                ClassDescriptor object = resolveJavaLangObject();
155                if (object != null) {
156                    result.add(object.getDefaultType());
157                }
158                else {
159                    //TODO: hack here
160                    result.add(KotlinBuiltIns.getInstance().getAnyType());
161                   // throw new IllegalStateException("Could not resolve java.lang.Object");
162                }
163            }
164        }
165    
166        private void reportIncompleteHierarchyForErrorTypes(ClassDescriptor classDescriptor, List<JetType> result) {
167            for (JetType supertype : result) {
168                if (ErrorUtils.isErrorType(supertype)) {
169                    trace.record(BindingContext.INCOMPLETE_HIERARCHY, classDescriptor);
170                }
171            }
172        }
173    
174        private void transformSupertypeList(
175                List<JetType> result,
176                PsiClassType[] extendsListTypes,
177                TypeVariableResolver typeVariableResolver
178        ) {
179            for (PsiClassType type : extendsListTypes) {
180                PsiClass resolved = type.resolve();
181                if (resolved != null) {
182                    String qualifiedName = resolved.getQualifiedName();
183                    assert qualifiedName != null;
184                    if (JvmStdlibNames.JET_OBJECT.getFqName().equalsTo(qualifiedName)) {
185                        continue;
186                    }
187                }
188    
189                JetType transform = typeTransformer
190                        .transformToType(type, TypeUsage.SUPERTYPE, typeVariableResolver);
191                if (ErrorUtils.isErrorType(transform)) {
192                    continue;
193                }
194    
195                result.add(TypeUtils.makeNotNullable(transform));
196            }
197        }
198    
199    
200        @Nullable
201        private ClassDescriptor resolveJavaLangObject() {
202            ClassDescriptor clazz = classResolver.resolveClass(DescriptorResolverUtils.OBJECT_FQ_NAME,
203                                                               DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN);
204            if (clazz == null) {
205                // TODO: warning
206            }
207            return clazz;
208        }
209    }