SymbolBasedClassifierType: fix exception in case with not found class

This can arise with non-transitive dependencies
#KT-33932 Fixed
This commit is contained in:
Mikhail Glukhikh
2019-09-19 18:21:26 +03:00
parent 6b8f4b4b4e
commit f74b3e6ece
2 changed files with 94 additions and 2 deletions
@@ -0,0 +1,85 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.javac.wrappers.symbols
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.search.SearchScope
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.javac.JavaClassWithClassId
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import javax.lang.model.element.TypeElement
import javax.lang.model.type.TypeKind
import javax.tools.JavaFileObject
// This represents Java class for which we don't have resolved classifier.
// The situation when it is useful is described in KT-33932.
// Mostly it's a stub.
class FakeSymbolBasedClass(
element: TypeElement,
javac: JavacWrapper,
override val classId: ClassId?,
val file: JavaFileObject?
) : SymbolBasedClassifier<TypeElement>(element, javac), JavaClassWithClassId {
override val name: Name get() = Name.identifier(element.simpleName.toString())
override val isAbstract: Boolean get() = true
override val isStatic: Boolean get() = false
override val isFinal: Boolean get() = false
override val visibility: Visibility get() = Visibilities.PUBLIC
override val typeParameters: List<JavaTypeParameter> get() = emptyList()
override val fqName: FqName get() = FqName(element.qualifiedName.toString())
override val supertypes: Collection<JavaClassifierType> get() = emptyList()
val innerClasses: Map<Name, JavaClass> get() = emptyMap()
override val outerClass: JavaClass?
by lazy {
element.enclosingElement?.let {
if (it.asType().kind != TypeKind.DECLARED) null else FakeSymbolBasedClass(
it as TypeElement,
javac,
classId?.outerClassId,
file
)
}
}
override val isInterface: Boolean get() = true
override val isAnnotationType: Boolean get() = false
override val isEnum: Boolean get() = false
override val lightClassOriginKind: LightClassOriginKind? get() = null
override val methods: Collection<JavaMethod> get() = emptyList()
override val fields: Collection<JavaField> get() = emptyList()
override val constructors: Collection<JavaConstructor> get() = emptyList()
override val innerClassNames: Collection<Name> get() = emptyList()
override val virtualFile: VirtualFile? by lazy {
file?.let { javac.toVirtualFile(it) }
}
override fun isFromSourceCodeInScope(scope: SearchScope): Boolean = false
override fun findInnerClass(name: Name): JavaClass? = null
}
@@ -71,13 +71,17 @@ class SymbolBasedClassifierType<out T : TypeMirror>(
javac: JavacWrapper
) : SymbolBasedType<T>(typeMirror, javac), JavaClassifierType {
private val isFake get() = classifier is FakeSymbolBasedClass
// TODO: we should replace this with a "link" to classifier, not an actual classifier itself
// It should be something like ConeClassifierLookupTag (see compiler:fir:cones)
override val classifier: JavaClassifier?
by lazy {
when (typeMirror.kind) {
TypeKind.DECLARED -> ((typeMirror as DeclaredType).asElement() as Symbol.ClassSymbol).let { symbol ->
// try to find cached javaClass
val classId = symbol.computeClassId()
classId?.let { javac.findClass(it) } ?: SymbolBasedClass(symbol, javac, classId, symbol.classfile)
classId?.let { javac.findClass(it) } ?: FakeSymbolBasedClass(symbol, javac, classId, symbol.classfile)
}
TypeKind.TYPEVAR -> SymbolBasedTypeParameter((typeMirror as TypeVariable).asElement() as TypeParameterElement, javac)
else -> null
@@ -86,7 +90,7 @@ class SymbolBasedClassifierType<out T : TypeMirror>(
override val typeArguments: List<JavaType>
get() {
if (typeMirror.kind != TypeKind.DECLARED) return emptyList()
if (typeMirror.kind != TypeKind.DECLARED || isFake) return emptyList()
val arguments = arrayListOf<JavaType>()
var type = typeMirror as DeclaredType
@@ -106,6 +110,7 @@ class SymbolBasedClassifierType<out T : TypeMirror>(
override val isRaw: Boolean
get() = when {
typeMirror !is DeclaredType -> false
isFake -> false
(classifier as? JavaClass)?.typeParameters?.isEmpty() == true -> false
else -> typeMirror.typeArguments.isEmpty() || (classifier as? JavaClass)?.typeParameters?.size != typeMirror.typeArguments.size
}
@@ -116,6 +121,8 @@ class SymbolBasedClassifierType<out T : TypeMirror>(
override val presentableText: String
get() = typeMirror.toString()
override val isDeprecatedInJavaDoc: Boolean
get() = !isFake && super.isDeprecatedInJavaDoc
}
class SymbolBasedWildcardType(