Extract ClassResolver class from JavaDescriptorResolver
This commit is contained in:
+1
-1
@@ -146,7 +146,7 @@ public class JavaDescriptorResolveData {
|
||||
super(negative);
|
||||
}
|
||||
|
||||
static final ResolverClassData NEGATIVE = new ResolverBinaryClassData(true);
|
||||
public static final ResolverClassData NEGATIVE = new ResolverBinaryClassData(true);
|
||||
}
|
||||
|
||||
public static class ResolverClassData extends ResolverScopeData {
|
||||
|
||||
+38
-145
@@ -32,13 +32,16 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.constants.*;
|
||||
import org.jetbrains.jet.lang.resolve.constants.StringValue;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData.*;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData.ResolverClassData;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData.ResolverNamespaceData;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData.ResolverScopeData;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData.ResolverSyntheticClassObjectClassData;
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaNamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeMethodSignatureData;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.PsiAnnotationWithFlags;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.ClassResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaDescriptorPropertiesResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.scope.JavaClassMembersScope;
|
||||
import org.jetbrains.jet.lang.resolve.java.scope.JavaPackageScope;
|
||||
@@ -121,6 +124,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
private PsiClassFinder psiClassFinder;
|
||||
private JavaDescriptorSignatureResolver javaDescriptorSignatureResolver;
|
||||
private JavaDescriptorPropertiesResolver javaDescriptorPropertiesResolver = new JavaDescriptorPropertiesResolver(this);
|
||||
private final ClassResolver classResolver = new ClassResolver(this);
|
||||
|
||||
@Inject
|
||||
public void setProject(Project project) {
|
||||
@@ -153,7 +157,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
|
||||
@Nullable
|
||||
private ClassDescriptor resolveJavaLangObject() {
|
||||
ClassDescriptor clazz = resolveClass(OBJECT_FQ_NAME, DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN);
|
||||
ClassDescriptor clazz = classResolver.resolveClass(OBJECT_FQ_NAME, DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN);
|
||||
if (clazz == null) {
|
||||
// TODO: warning
|
||||
}
|
||||
@@ -162,148 +166,32 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
|
||||
@Nullable
|
||||
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
|
||||
List<Runnable> tasks = Lists.newArrayList();
|
||||
ClassDescriptor clazz = resolveClass(qualifiedName, searchRule, tasks);
|
||||
for (Runnable task : tasks) {
|
||||
task.run();
|
||||
}
|
||||
return clazz;
|
||||
return classResolver.resolveClass(qualifiedName, searchRule);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName) {
|
||||
return resolveClass(qualifiedName, DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN);
|
||||
return classResolver.resolveClass(qualifiedName);
|
||||
}
|
||||
|
||||
private ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule, @NotNull List<Runnable> tasks) {
|
||||
if (qualifiedName.getFqName().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) {
|
||||
// TODO: only if -$$TImpl class is created by Kotlin
|
||||
return null;
|
||||
}
|
||||
|
||||
ClassDescriptor builtinClassDescriptor = semanticServices.getKotlinBuiltinClassDescriptor(qualifiedName);
|
||||
if (builtinClassDescriptor != null) {
|
||||
return builtinClassDescriptor;
|
||||
}
|
||||
|
||||
// First, let's check that this is a real Java class, not a Java's view on a Kotlin class:
|
||||
ClassDescriptor kotlinClassDescriptor = semanticServices.getKotlinClassDescriptor(qualifiedName);
|
||||
if (kotlinClassDescriptor != null) {
|
||||
if (searchRule == DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN) {
|
||||
throw new IllegalStateException("class must not be found in kotlin: " + qualifiedName);
|
||||
}
|
||||
else if (searchRule == DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN) {
|
||||
return null;
|
||||
}
|
||||
else if (searchRule == DescriptorSearchRule.INCLUDE_KOTLIN) {
|
||||
return kotlinClassDescriptor;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("unknown searchRule: " + searchRule);
|
||||
}
|
||||
}
|
||||
|
||||
// Not let's take a descriptor of a Java class
|
||||
ResolverClassData classData = classDescriptorCache.get(qualifiedName);
|
||||
if (classData == null) {
|
||||
PsiClass psiClass = psiClassFinder.findPsiClass(qualifiedName, PsiClassFinder.RuntimeClassesHandleMode.THROW);
|
||||
if (psiClass == null) {
|
||||
ResolverClassData oldValue = classDescriptorCache.put(qualifiedName, ResolverBinaryClassData.NEGATIVE);
|
||||
if (oldValue != null) {
|
||||
throw new IllegalStateException("rewrite at " + qualifiedName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
classData = createJavaClassDescriptor(psiClass, tasks);
|
||||
}
|
||||
return classData.getClassDescriptor();
|
||||
public PsiClassFinder getPsiClassFinder() {
|
||||
return psiClassFinder;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ResolverClassData createJavaClassDescriptor(@NotNull final PsiClass psiClass, List<Runnable> taskList) {
|
||||
final String qualifiedName = psiClass.getQualifiedName();
|
||||
assert qualifiedName != null;
|
||||
|
||||
FqName fqName = new FqName(qualifiedName);
|
||||
if (classDescriptorCache.containsKey(fqName)) {
|
||||
throw new IllegalStateException(qualifiedName);
|
||||
}
|
||||
|
||||
checkPsiClassIsNotJet(psiClass);
|
||||
|
||||
Name name = Name.identifier(psiClass.getName());
|
||||
JetClassAnnotation jetClassAnnotation = JetClassAnnotation.get(psiClass);
|
||||
ClassKind kind = getClassKind(psiClass, jetClassAnnotation);
|
||||
ClassOrNamespaceDescriptor containingDeclaration = resolveParentDescriptor(psiClass);
|
||||
|
||||
// class may be resolved during resolution of parent
|
||||
ResolverClassData classData = classDescriptorCache.get(fqName);
|
||||
if (classData != null) {
|
||||
return classData;
|
||||
}
|
||||
|
||||
classData = new ClassDescriptorFromJvmBytecode(
|
||||
containingDeclaration, kind, psiClass, fqName, this)
|
||||
.getResolverBinaryClassData();
|
||||
classDescriptorCache.put(fqName, classData);
|
||||
classData.getClassDescriptor().setName(name);
|
||||
|
||||
List<JetType> supertypes = new ArrayList<JetType>();
|
||||
|
||||
List<JavaDescriptorSignatureResolver.TypeParameterDescriptorInitialization> typeParameterDescriptorInitializations
|
||||
= javaDescriptorSignatureResolver.createUninitializedClassTypeParameters(psiClass, classData);
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>();
|
||||
for (JavaDescriptorSignatureResolver.TypeParameterDescriptorInitialization typeParameter : typeParameterDescriptorInitializations) {
|
||||
typeParameters.add(typeParameter.descriptor);
|
||||
}
|
||||
|
||||
classData.getClassDescriptor().setTypeParameterDescriptors(typeParameters);
|
||||
classData.getClassDescriptor().setSupertypes(supertypes);
|
||||
classData.getClassDescriptor().setVisibility(resolveVisibility(psiClass, jetClassAnnotation));
|
||||
Modality modality;
|
||||
if (classData.getClassDescriptor().getKind() == ClassKind.ANNOTATION_CLASS) {
|
||||
modality = Modality.FINAL;
|
||||
}
|
||||
else {
|
||||
modality = Modality.convertFromFlags(
|
||||
psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface(),
|
||||
!psiClass.hasModifierProperty(PsiModifier.FINAL));
|
||||
}
|
||||
classData.getClassDescriptor().setModality(modality);
|
||||
classData.getClassDescriptor().createTypeConstructor();
|
||||
classData.getClassDescriptor().setScopeForMemberLookup(new JavaClassMembersScope(semanticServices, classData));
|
||||
|
||||
javaDescriptorSignatureResolver.initializeTypeParameters(typeParameterDescriptorInitializations, classData.getClassDescriptor(), "class " + qualifiedName);
|
||||
|
||||
// TODO: ugly hack: tests crash if initializeTypeParameters called with class containing proper supertypes
|
||||
List<TypeParameterDescriptor> classTypeParameters = classData.getClassDescriptor().getTypeConstructor().getParameters();
|
||||
supertypes.addAll(getSupertypes(new PsiClassWrapper(psiClass), classData, classTypeParameters));
|
||||
|
||||
MutableClassDescriptorLite classObject = createClassObjectDescriptor(classData.getClassDescriptor(), psiClass);
|
||||
if (classObject != null) {
|
||||
classData.getClassDescriptor().getBuilder().setClassObjectDescriptor(classObject);
|
||||
}
|
||||
|
||||
classData.getClassDescriptor().setAnnotations(resolveAnnotations(psiClass, taskList));
|
||||
|
||||
trace.record(BindingContext.CLASS, psiClass, classData.getClassDescriptor());
|
||||
|
||||
return classData;
|
||||
public Map<FqNameBase, ResolverClassData> getClassDescriptorCache() {
|
||||
return classDescriptorCache;
|
||||
}
|
||||
|
||||
private static ClassKind getClassKind(@NotNull PsiClass psiClass, @NotNull JetClassAnnotation jetClassAnnotation) {
|
||||
if (psiClass.isInterface()) {
|
||||
return (psiClass.isAnnotationType() ? ClassKind.ANNOTATION_CLASS : ClassKind.TRAIT);
|
||||
}
|
||||
else {
|
||||
if (psiClass.isEnum()) {
|
||||
return ClassKind.ENUM_CLASS;
|
||||
}
|
||||
else {
|
||||
return jetClassAnnotation.kind() == JvmStdlibNames.FLAG_CLASS_KIND_OBJECT ? ClassKind.OBJECT : ClassKind.CLASS;
|
||||
}
|
||||
}
|
||||
public JavaDescriptorSignatureResolver getJavaDescriptorSignatureResolver() {
|
||||
return javaDescriptorSignatureResolver;
|
||||
}
|
||||
|
||||
public JavaSemanticServices getSemanticServices() {
|
||||
return semanticServices;
|
||||
}
|
||||
|
||||
public BindingTrace getTrace() {
|
||||
return trace;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -446,7 +334,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
return constructorDescriptor;
|
||||
}
|
||||
|
||||
static void checkPsiClassIsNotJet(PsiClass psiClass) {
|
||||
public static void checkPsiClassIsNotJet(PsiClass psiClass) {
|
||||
if (psiClass instanceof JetJavaMirrorMarker) {
|
||||
throw new IllegalStateException("trying to resolve fake jet PsiClass as regular PsiClass: " + psiClass.getQualifiedName());
|
||||
}
|
||||
@@ -467,7 +355,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
//* @see #createJavaNamespaceDescriptor(PsiClass)
|
||||
*/
|
||||
@Nullable
|
||||
private MutableClassDescriptorLite createClassObjectDescriptor(@NotNull ClassDescriptor containing, @NotNull PsiClass psiClass) {
|
||||
public MutableClassDescriptorLite createClassObjectDescriptor(@NotNull ClassDescriptor containing, @NotNull PsiClass psiClass) {
|
||||
checkPsiClassIsNotJet(psiClass);
|
||||
|
||||
if (psiClass.isEnum()) {
|
||||
@@ -567,7 +455,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
|
||||
|
||||
@NotNull
|
||||
private ClassOrNamespaceDescriptor resolveParentDescriptor(@NotNull PsiClass psiClass) {
|
||||
public ClassOrNamespaceDescriptor resolveParentDescriptor(@NotNull PsiClass psiClass) {
|
||||
final String qualifiedName = psiClass.getQualifiedName();
|
||||
assert qualifiedName != null;
|
||||
FqName fqName = new FqName(qualifiedName);
|
||||
@@ -577,7 +465,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
final String containingClassQualifiedName = containingClass.getQualifiedName();
|
||||
assert containingClassQualifiedName != null;
|
||||
FqName containerFqName = new FqName(containingClassQualifiedName);
|
||||
ClassDescriptor clazz = resolveClass(containerFqName, DescriptorSearchRule.INCLUDE_KOTLIN);
|
||||
ClassDescriptor clazz = classResolver.resolveClass(containerFqName, DescriptorSearchRule.INCLUDE_KOTLIN);
|
||||
if (clazz == null) {
|
||||
throw new IllegalStateException("PsiClass not found by name " + containerFqName + ", required to be container declaration of " + fqName);
|
||||
}
|
||||
@@ -598,7 +486,11 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
return ns;
|
||||
}
|
||||
|
||||
private Collection<JetType> getSupertypes(PsiClassWrapper psiClass, ResolverClassData classData, List<TypeParameterDescriptor> typeParameters) {
|
||||
public Collection<JetType> getSupertypes(
|
||||
PsiClassWrapper psiClass,
|
||||
ResolverClassData classData,
|
||||
List<TypeParameterDescriptor> typeParameters
|
||||
) {
|
||||
ClassDescriptor classDescriptor = classData.getClassDescriptor();
|
||||
|
||||
final List<JetType> result = new ArrayList<JetType>();
|
||||
@@ -1175,7 +1067,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
return (methodName.equals("values") && methodTypeParameters.isEmpty());
|
||||
}
|
||||
|
||||
private List<AnnotationDescriptor> resolveAnnotations(PsiModifierListOwner owner, @NotNull List<Runnable> tasks) {
|
||||
public List<AnnotationDescriptor> resolveAnnotations(PsiModifierListOwner owner, @NotNull List<Runnable> tasks) {
|
||||
PsiAnnotation[] psiAnnotations = getAllAnnotations(owner);
|
||||
List<AnnotationDescriptor> r = Lists.newArrayListWithCapacity(psiAnnotations.length);
|
||||
for (PsiAnnotation psiAnnotation : psiAnnotations) {
|
||||
@@ -1210,7 +1102,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
}
|
||||
|
||||
FqName annotationFqName = new FqName(qname);
|
||||
final ClassDescriptor clazz = resolveClass(annotationFqName, DescriptorSearchRule.INCLUDE_KOTLIN, taskList);
|
||||
final ClassDescriptor clazz = classResolver.resolveClass(annotationFqName, DescriptorSearchRule.INCLUDE_KOTLIN, taskList);
|
||||
if (clazz == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -1301,7 +1193,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
PsiAnnotationMemberValue[] initializers = value.getInitializers();
|
||||
List<CompileTimeConstant<?>> values = getCompileTimeConstantForArrayValues(annotationFqName, valueName, taskList, initializers);
|
||||
|
||||
ClassDescriptor classDescriptor = resolveClass(annotationFqName, DescriptorSearchRule.INCLUDE_KOTLIN, taskList);
|
||||
ClassDescriptor classDescriptor = classResolver.resolveClass(annotationFqName, DescriptorSearchRule.INCLUDE_KOTLIN, taskList);
|
||||
|
||||
ValueParameterDescriptor valueParameterDescriptor = getValueParameterDescriptorForAnnotationParameter(valueName, classDescriptor);
|
||||
if (valueParameterDescriptor == null) {
|
||||
@@ -1342,7 +1234,8 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
}
|
||||
|
||||
JetScope scope;
|
||||
ClassDescriptor classDescriptor = resolveClass(new FqName(fqName), DescriptorSearchRule.INCLUDE_KOTLIN, taskList);
|
||||
ClassDescriptor classDescriptor =
|
||||
classResolver.resolveClass(new FqName(fqName), DescriptorSearchRule.INCLUDE_KOTLIN, taskList);
|
||||
if (classDescriptor == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -1527,7 +1420,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
private ClassDescriptor resolveInnerClass(@NotNull PsiClass innerPsiClass) {
|
||||
String name = innerPsiClass.getQualifiedName();
|
||||
assert name != null : "Inner class has no qualified name";
|
||||
ClassDescriptor classDescriptor = resolveClass(new FqName(name), DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN);
|
||||
ClassDescriptor classDescriptor = classResolver.resolveClass(new FqName(name), DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN);
|
||||
assert classDescriptor != null : "Couldn't resolve class " + name;
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
+16
-4
@@ -66,8 +66,8 @@ public class JavaDescriptorSignatureResolver {
|
||||
@NotNull
|
||||
private final TypeParameterDescriptorOrigin origin;
|
||||
@NotNull
|
||||
final TypeParameterDescriptorImpl descriptor;
|
||||
final PsiTypeParameter psiTypeParameter;
|
||||
private final TypeParameterDescriptorImpl descriptor;
|
||||
private final PsiTypeParameter psiTypeParameter;
|
||||
@Nullable
|
||||
private final List<JetType> upperBoundsForKotlin;
|
||||
|
||||
@@ -87,6 +87,11 @@ public class JavaDescriptorSignatureResolver {
|
||||
this.psiTypeParameter = psiTypeParameter;
|
||||
this.upperBoundsForKotlin = upperBoundsForKotlin;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TypeParameterDescriptorImpl getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -298,7 +303,11 @@ public class JavaDescriptorSignatureResolver {
|
||||
typeParameterDescriptor.setInitialized();
|
||||
}
|
||||
|
||||
void initializeTypeParameters(List<TypeParameterDescriptorInitialization> typeParametersInitialization, @NotNull DeclarationDescriptor typeParametersOwner, @NotNull String context) {
|
||||
public void initializeTypeParameters(
|
||||
List<TypeParameterDescriptorInitialization> typeParametersInitialization,
|
||||
@NotNull DeclarationDescriptor typeParametersOwner,
|
||||
@NotNull String context
|
||||
) {
|
||||
List<TypeParameterDescriptor> prevTypeParameters = Lists.newArrayList();
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = Lists.newArrayList();
|
||||
@@ -314,7 +323,10 @@ public class JavaDescriptorSignatureResolver {
|
||||
}
|
||||
|
||||
|
||||
List<TypeParameterDescriptorInitialization> createUninitializedClassTypeParameters(PsiClass psiClass, ResolverClassData classData) {
|
||||
public List<TypeParameterDescriptorInitialization> createUninitializedClassTypeParameters(
|
||||
PsiClass psiClass,
|
||||
ResolverClassData classData
|
||||
) {
|
||||
JetClassAnnotation jetClassAnnotation = JetClassAnnotation.get(psiClass);
|
||||
|
||||
if (jetClassAnnotation.signature().length() > 0) {
|
||||
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.java.resolver;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.*;
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation;
|
||||
import org.jetbrains.jet.lang.resolve.java.scope.JavaClassMembersScope;
|
||||
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiClassWrapper;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ClassResolver {
|
||||
private final JavaDescriptorResolver javaDescriptorResolver;
|
||||
|
||||
public ClassResolver(JavaDescriptorResolver javaDescriptorResolver) {
|
||||
this.javaDescriptorResolver = javaDescriptorResolver;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
|
||||
List<Runnable> tasks = Lists.newArrayList();
|
||||
ClassDescriptor clazz = resolveClass(qualifiedName, searchRule, tasks);
|
||||
for (Runnable task : tasks) {
|
||||
task.run();
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName) {
|
||||
return resolveClass(qualifiedName, DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN);
|
||||
}
|
||||
|
||||
public ClassDescriptor resolveClass(
|
||||
@NotNull FqName qualifiedName,
|
||||
@NotNull DescriptorSearchRule searchRule,
|
||||
@NotNull List<Runnable> tasks
|
||||
) {
|
||||
if (qualifiedName.getFqName().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) {
|
||||
// TODO: only if -$$TImpl class is created by Kotlin
|
||||
return null;
|
||||
}
|
||||
|
||||
ClassDescriptor builtinClassDescriptor =
|
||||
javaDescriptorResolver.getSemanticServices().getKotlinBuiltinClassDescriptor(qualifiedName);
|
||||
if (builtinClassDescriptor != null) {
|
||||
return builtinClassDescriptor;
|
||||
}
|
||||
|
||||
// First, let's check that this is a real Java class, not a Java's view on a Kotlin class:
|
||||
ClassDescriptor kotlinClassDescriptor = javaDescriptorResolver.getSemanticServices().getKotlinClassDescriptor(qualifiedName);
|
||||
if (kotlinClassDescriptor != null) {
|
||||
if (searchRule == DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN) {
|
||||
throw new IllegalStateException("class must not be found in kotlin: " + qualifiedName);
|
||||
}
|
||||
else if (searchRule == DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN) {
|
||||
return null;
|
||||
}
|
||||
else if (searchRule == DescriptorSearchRule.INCLUDE_KOTLIN) {
|
||||
return kotlinClassDescriptor;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("unknown searchRule: " + searchRule);
|
||||
}
|
||||
}
|
||||
|
||||
// Not let's take a descriptor of a Java class
|
||||
JavaDescriptorResolveData.ResolverClassData classData = javaDescriptorResolver.getClassDescriptorCache().get(qualifiedName);
|
||||
if (classData == null) {
|
||||
PsiClass psiClass =
|
||||
javaDescriptorResolver.getPsiClassFinder().findPsiClass(qualifiedName, PsiClassFinder.RuntimeClassesHandleMode.THROW);
|
||||
if (psiClass == null) {
|
||||
JavaDescriptorResolveData.ResolverClassData oldValue =
|
||||
javaDescriptorResolver.getClassDescriptorCache().put(qualifiedName, JavaDescriptorResolveData.ResolverBinaryClassData.NEGATIVE);
|
||||
if (oldValue != null) {
|
||||
throw new IllegalStateException("rewrite at " + qualifiedName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
classData = createJavaClassDescriptor(psiClass, tasks);
|
||||
}
|
||||
return classData.getClassDescriptor();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JavaDescriptorResolveData.ResolverClassData createJavaClassDescriptor(
|
||||
@NotNull final PsiClass psiClass,
|
||||
List<Runnable> taskList
|
||||
) {
|
||||
final String qualifiedName = psiClass.getQualifiedName();
|
||||
assert qualifiedName != null;
|
||||
|
||||
FqName fqName = new FqName(qualifiedName);
|
||||
if (javaDescriptorResolver.getClassDescriptorCache().containsKey(fqName)) {
|
||||
throw new IllegalStateException(qualifiedName);
|
||||
}
|
||||
|
||||
JavaDescriptorResolver.checkPsiClassIsNotJet(psiClass);
|
||||
|
||||
Name name = Name.identifier(psiClass.getName());
|
||||
JetClassAnnotation jetClassAnnotation = JetClassAnnotation.get(psiClass);
|
||||
ClassKind kind = getClassKind(psiClass, jetClassAnnotation);
|
||||
ClassOrNamespaceDescriptor containingDeclaration = javaDescriptorResolver.resolveParentDescriptor(psiClass);
|
||||
|
||||
// class may be resolved during resolution of parent
|
||||
JavaDescriptorResolveData.ResolverClassData classData = javaDescriptorResolver.getClassDescriptorCache().get(fqName);
|
||||
if (classData != null) {
|
||||
return classData;
|
||||
}
|
||||
|
||||
classData = new ClassDescriptorFromJvmBytecode(
|
||||
containingDeclaration, kind, psiClass, fqName, javaDescriptorResolver)
|
||||
.getResolverBinaryClassData();
|
||||
javaDescriptorResolver.getClassDescriptorCache().put(fqName, classData);
|
||||
classData.getClassDescriptor().setName(name);
|
||||
|
||||
List<JetType> supertypes = new ArrayList<JetType>();
|
||||
|
||||
List<JavaDescriptorSignatureResolver.TypeParameterDescriptorInitialization> typeParameterDescriptorInitializations
|
||||
= javaDescriptorResolver.getJavaDescriptorSignatureResolver().createUninitializedClassTypeParameters(psiClass, classData);
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>();
|
||||
for (JavaDescriptorSignatureResolver.TypeParameterDescriptorInitialization typeParameter : typeParameterDescriptorInitializations) {
|
||||
typeParameters.add(typeParameter.getDescriptor());
|
||||
}
|
||||
|
||||
classData.getClassDescriptor().setTypeParameterDescriptors(typeParameters);
|
||||
classData.getClassDescriptor().setSupertypes(supertypes);
|
||||
classData.getClassDescriptor().setVisibility(JavaDescriptorResolver.resolveVisibility(psiClass, jetClassAnnotation));
|
||||
Modality modality;
|
||||
if (classData.getClassDescriptor().getKind() == ClassKind.ANNOTATION_CLASS) {
|
||||
modality = Modality.FINAL;
|
||||
}
|
||||
else {
|
||||
modality = Modality.convertFromFlags(
|
||||
psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface(),
|
||||
!psiClass.hasModifierProperty(PsiModifier.FINAL));
|
||||
}
|
||||
classData.getClassDescriptor().setModality(modality);
|
||||
classData.getClassDescriptor().createTypeConstructor();
|
||||
classData.getClassDescriptor()
|
||||
.setScopeForMemberLookup(new JavaClassMembersScope(javaDescriptorResolver.getSemanticServices(), classData));
|
||||
|
||||
javaDescriptorResolver.getJavaDescriptorSignatureResolver()
|
||||
.initializeTypeParameters(typeParameterDescriptorInitializations, classData.getClassDescriptor(), "class " + qualifiedName);
|
||||
|
||||
// TODO: ugly hack: tests crash if initializeTypeParameters called with class containing proper supertypes
|
||||
List<TypeParameterDescriptor> classTypeParameters = classData.getClassDescriptor().getTypeConstructor().getParameters();
|
||||
supertypes.addAll(javaDescriptorResolver.getSupertypes(new PsiClassWrapper(psiClass), classData, classTypeParameters));
|
||||
|
||||
MutableClassDescriptorLite classObject =
|
||||
javaDescriptorResolver.createClassObjectDescriptor(classData.getClassDescriptor(), psiClass);
|
||||
if (classObject != null) {
|
||||
classData.getClassDescriptor().getBuilder().setClassObjectDescriptor(classObject);
|
||||
}
|
||||
|
||||
classData.getClassDescriptor().setAnnotations(javaDescriptorResolver.resolveAnnotations(psiClass, taskList));
|
||||
|
||||
javaDescriptorResolver.getTrace().record(BindingContext.CLASS, psiClass, classData.getClassDescriptor());
|
||||
|
||||
return classData;
|
||||
}
|
||||
|
||||
public static ClassKind getClassKind(@NotNull PsiClass psiClass, @NotNull JetClassAnnotation jetClassAnnotation) {
|
||||
if (psiClass.isInterface()) {
|
||||
return (psiClass.isAnnotationType() ? ClassKind.ANNOTATION_CLASS : ClassKind.TRAIT);
|
||||
}
|
||||
else {
|
||||
if (psiClass.isEnum()) {
|
||||
return ClassKind.ENUM_CLASS;
|
||||
}
|
||||
else {
|
||||
return jetClassAnnotation.kind() == JvmStdlibNames.FLAG_CLASS_KIND_OBJECT ? ClassKind.OBJECT : ClassKind.CLASS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user