Extract ClassResolver class from JavaDescriptorResolver
This commit is contained in:
+1
-1
@@ -146,7 +146,7 @@ public class JavaDescriptorResolveData {
|
|||||||
super(negative);
|
super(negative);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final ResolverClassData NEGATIVE = new ResolverBinaryClassData(true);
|
public static final ResolverClassData NEGATIVE = new ResolverBinaryClassData(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ResolverClassData extends ResolverScopeData {
|
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.*;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.*;
|
import org.jetbrains.jet.lang.resolve.constants.*;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.StringValue;
|
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.ClassDescriptorFromJvmBytecode;
|
||||||
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaNamespaceDescriptor;
|
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.kotlinSignature.AlternativeMethodSignatureData;
|
||||||
import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
|
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.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.resolver.JavaDescriptorPropertiesResolver;
|
||||||
import org.jetbrains.jet.lang.resolve.java.scope.JavaClassMembersScope;
|
import org.jetbrains.jet.lang.resolve.java.scope.JavaClassMembersScope;
|
||||||
import org.jetbrains.jet.lang.resolve.java.scope.JavaPackageScope;
|
import org.jetbrains.jet.lang.resolve.java.scope.JavaPackageScope;
|
||||||
@@ -121,6 +124,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
|||||||
private PsiClassFinder psiClassFinder;
|
private PsiClassFinder psiClassFinder;
|
||||||
private JavaDescriptorSignatureResolver javaDescriptorSignatureResolver;
|
private JavaDescriptorSignatureResolver javaDescriptorSignatureResolver;
|
||||||
private JavaDescriptorPropertiesResolver javaDescriptorPropertiesResolver = new JavaDescriptorPropertiesResolver(this);
|
private JavaDescriptorPropertiesResolver javaDescriptorPropertiesResolver = new JavaDescriptorPropertiesResolver(this);
|
||||||
|
private final ClassResolver classResolver = new ClassResolver(this);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public void setProject(Project project) {
|
public void setProject(Project project) {
|
||||||
@@ -153,7 +157,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private ClassDescriptor resolveJavaLangObject() {
|
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) {
|
if (clazz == null) {
|
||||||
// TODO: warning
|
// TODO: warning
|
||||||
}
|
}
|
||||||
@@ -162,148 +166,32 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
|
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
|
||||||
List<Runnable> tasks = Lists.newArrayList();
|
return classResolver.resolveClass(qualifiedName, searchRule);
|
||||||
ClassDescriptor clazz = resolveClass(qualifiedName, searchRule, tasks);
|
|
||||||
for (Runnable task : tasks) {
|
|
||||||
task.run();
|
|
||||||
}
|
|
||||||
return clazz;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName) {
|
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) {
|
public PsiClassFinder getPsiClassFinder() {
|
||||||
if (qualifiedName.getFqName().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) {
|
return psiClassFinder;
|
||||||
// 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
public Map<FqNameBase, ResolverClassData> getClassDescriptorCache() {
|
||||||
private ResolverClassData createJavaClassDescriptor(@NotNull final PsiClass psiClass, List<Runnable> taskList) {
|
return classDescriptorCache;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ClassKind getClassKind(@NotNull PsiClass psiClass, @NotNull JetClassAnnotation jetClassAnnotation) {
|
public JavaDescriptorSignatureResolver getJavaDescriptorSignatureResolver() {
|
||||||
if (psiClass.isInterface()) {
|
return javaDescriptorSignatureResolver;
|
||||||
return (psiClass.isAnnotationType() ? ClassKind.ANNOTATION_CLASS : ClassKind.TRAIT);
|
}
|
||||||
}
|
|
||||||
else {
|
public JavaSemanticServices getSemanticServices() {
|
||||||
if (psiClass.isEnum()) {
|
return semanticServices;
|
||||||
return ClassKind.ENUM_CLASS;
|
}
|
||||||
}
|
|
||||||
else {
|
public BindingTrace getTrace() {
|
||||||
return jetClassAnnotation.kind() == JvmStdlibNames.FLAG_CLASS_KIND_OBJECT ? ClassKind.OBJECT : ClassKind.CLASS;
|
return trace;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -446,7 +334,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
|||||||
return constructorDescriptor;
|
return constructorDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkPsiClassIsNotJet(PsiClass psiClass) {
|
public static void checkPsiClassIsNotJet(PsiClass psiClass) {
|
||||||
if (psiClass instanceof JetJavaMirrorMarker) {
|
if (psiClass instanceof JetJavaMirrorMarker) {
|
||||||
throw new IllegalStateException("trying to resolve fake jet PsiClass as regular PsiClass: " + psiClass.getQualifiedName());
|
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)
|
//* @see #createJavaNamespaceDescriptor(PsiClass)
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
private MutableClassDescriptorLite createClassObjectDescriptor(@NotNull ClassDescriptor containing, @NotNull PsiClass psiClass) {
|
public MutableClassDescriptorLite createClassObjectDescriptor(@NotNull ClassDescriptor containing, @NotNull PsiClass psiClass) {
|
||||||
checkPsiClassIsNotJet(psiClass);
|
checkPsiClassIsNotJet(psiClass);
|
||||||
|
|
||||||
if (psiClass.isEnum()) {
|
if (psiClass.isEnum()) {
|
||||||
@@ -567,7 +455,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
|||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private ClassOrNamespaceDescriptor resolveParentDescriptor(@NotNull PsiClass psiClass) {
|
public ClassOrNamespaceDescriptor resolveParentDescriptor(@NotNull PsiClass psiClass) {
|
||||||
final String qualifiedName = psiClass.getQualifiedName();
|
final String qualifiedName = psiClass.getQualifiedName();
|
||||||
assert qualifiedName != null;
|
assert qualifiedName != null;
|
||||||
FqName fqName = new FqName(qualifiedName);
|
FqName fqName = new FqName(qualifiedName);
|
||||||
@@ -577,7 +465,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
|||||||
final String containingClassQualifiedName = containingClass.getQualifiedName();
|
final String containingClassQualifiedName = containingClass.getQualifiedName();
|
||||||
assert containingClassQualifiedName != null;
|
assert containingClassQualifiedName != null;
|
||||||
FqName containerFqName = new FqName(containingClassQualifiedName);
|
FqName containerFqName = new FqName(containingClassQualifiedName);
|
||||||
ClassDescriptor clazz = resolveClass(containerFqName, DescriptorSearchRule.INCLUDE_KOTLIN);
|
ClassDescriptor clazz = classResolver.resolveClass(containerFqName, DescriptorSearchRule.INCLUDE_KOTLIN);
|
||||||
if (clazz == null) {
|
if (clazz == null) {
|
||||||
throw new IllegalStateException("PsiClass not found by name " + containerFqName + ", required to be container declaration of " + fqName);
|
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;
|
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();
|
ClassDescriptor classDescriptor = classData.getClassDescriptor();
|
||||||
|
|
||||||
final List<JetType> result = new ArrayList<JetType>();
|
final List<JetType> result = new ArrayList<JetType>();
|
||||||
@@ -1175,7 +1067,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
|||||||
return (methodName.equals("values") && methodTypeParameters.isEmpty());
|
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);
|
PsiAnnotation[] psiAnnotations = getAllAnnotations(owner);
|
||||||
List<AnnotationDescriptor> r = Lists.newArrayListWithCapacity(psiAnnotations.length);
|
List<AnnotationDescriptor> r = Lists.newArrayListWithCapacity(psiAnnotations.length);
|
||||||
for (PsiAnnotation psiAnnotation : psiAnnotations) {
|
for (PsiAnnotation psiAnnotation : psiAnnotations) {
|
||||||
@@ -1210,7 +1102,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
|||||||
}
|
}
|
||||||
|
|
||||||
FqName annotationFqName = new FqName(qname);
|
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) {
|
if (clazz == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1301,7 +1193,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
|||||||
PsiAnnotationMemberValue[] initializers = value.getInitializers();
|
PsiAnnotationMemberValue[] initializers = value.getInitializers();
|
||||||
List<CompileTimeConstant<?>> values = getCompileTimeConstantForArrayValues(annotationFqName, valueName, taskList, initializers);
|
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);
|
ValueParameterDescriptor valueParameterDescriptor = getValueParameterDescriptorForAnnotationParameter(valueName, classDescriptor);
|
||||||
if (valueParameterDescriptor == null) {
|
if (valueParameterDescriptor == null) {
|
||||||
@@ -1342,7 +1234,8 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
|||||||
}
|
}
|
||||||
|
|
||||||
JetScope scope;
|
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) {
|
if (classDescriptor == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1527,7 +1420,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
|||||||
private ClassDescriptor resolveInnerClass(@NotNull PsiClass innerPsiClass) {
|
private ClassDescriptor resolveInnerClass(@NotNull PsiClass innerPsiClass) {
|
||||||
String name = innerPsiClass.getQualifiedName();
|
String name = innerPsiClass.getQualifiedName();
|
||||||
assert name != null : "Inner class has no qualified name";
|
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;
|
assert classDescriptor != null : "Couldn't resolve class " + name;
|
||||||
return classDescriptor;
|
return classDescriptor;
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-4
@@ -66,8 +66,8 @@ public class JavaDescriptorSignatureResolver {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final TypeParameterDescriptorOrigin origin;
|
private final TypeParameterDescriptorOrigin origin;
|
||||||
@NotNull
|
@NotNull
|
||||||
final TypeParameterDescriptorImpl descriptor;
|
private final TypeParameterDescriptorImpl descriptor;
|
||||||
final PsiTypeParameter psiTypeParameter;
|
private final PsiTypeParameter psiTypeParameter;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final List<JetType> upperBoundsForKotlin;
|
private final List<JetType> upperBoundsForKotlin;
|
||||||
|
|
||||||
@@ -87,6 +87,11 @@ public class JavaDescriptorSignatureResolver {
|
|||||||
this.psiTypeParameter = psiTypeParameter;
|
this.psiTypeParameter = psiTypeParameter;
|
||||||
this.upperBoundsForKotlin = upperBoundsForKotlin;
|
this.upperBoundsForKotlin = upperBoundsForKotlin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public TypeParameterDescriptorImpl getDescriptor() {
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -298,7 +303,11 @@ public class JavaDescriptorSignatureResolver {
|
|||||||
typeParameterDescriptor.setInitialized();
|
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> prevTypeParameters = Lists.newArrayList();
|
||||||
|
|
||||||
List<TypeParameterDescriptor> typeParameters = 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);
|
JetClassAnnotation jetClassAnnotation = JetClassAnnotation.get(psiClass);
|
||||||
|
|
||||||
if (jetClassAnnotation.signature().length() > 0) {
|
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