Support basic light-classes basic with FIR for CLI
This commit is contained in:
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* 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.fir.java
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Pair
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.cache.ModifierFlags
|
||||
import com.intellij.psi.impl.compiled.ClsClassImpl
|
||||
import com.intellij.psi.impl.compiled.ClsFileImpl
|
||||
import com.intellij.psi.impl.file.PsiPackageImpl
|
||||
import com.intellij.psi.impl.java.stubs.*
|
||||
import com.intellij.psi.impl.java.stubs.impl.*
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.classId
|
||||
import org.jetbrains.kotlin.fir.declarations.superConeTypes
|
||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.directExpansionType
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.service
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||
import org.jetbrains.kotlin.resolve.jvm.KotlinFinderMarker
|
||||
|
||||
class FirJavaElementFinder(
|
||||
private val session: FirSession,
|
||||
project: Project
|
||||
) : PsiElementFinder(), KotlinFinderMarker {
|
||||
private val psiManager = PsiManager.getInstance(project)
|
||||
private val firProvider = session.service<FirProvider>()
|
||||
|
||||
override fun findPackage(qualifiedName: String): PsiPackage? {
|
||||
if (firProvider.getClassNamesInPackage(FqName(qualifiedName)).isEmpty()) return null
|
||||
return PsiPackageImpl(psiManager, qualifiedName)
|
||||
}
|
||||
|
||||
override fun getClasses(psiPackage: PsiPackage, scope: GlobalSearchScope): Array<PsiClass> {
|
||||
return firProvider
|
||||
.getClassNamesInPackage(FqName(psiPackage.qualifiedName))
|
||||
.mapNotNull { findClass(psiPackage.qualifiedName + "." + it.identifier, scope) }
|
||||
.toTypedArray()
|
||||
}
|
||||
|
||||
override fun findClasses(qualifiedName: String, scope: GlobalSearchScope): Array<PsiClass> {
|
||||
return findClass(qualifiedName, scope)?.let(::arrayOf) ?: emptyArray()
|
||||
}
|
||||
|
||||
override fun findClass(qualifiedName: String, scope: GlobalSearchScope): PsiClass? {
|
||||
val classId = ClassId.topLevel(FqName(qualifiedName))
|
||||
|
||||
val firClass =
|
||||
firProvider.getFirClassifierByFqName(classId) as? FirRegularClass
|
||||
?: return null
|
||||
|
||||
val ktFile = firClass.psi?.containingFile as KtFile
|
||||
val fileStub = createJavaFileStub(classId.packageFqName, listOf(ktFile))
|
||||
|
||||
return buildStub(firClass, fileStub).psi
|
||||
}
|
||||
|
||||
private fun buildStub(firClass: FirRegularClass, parent: StubElement<*>): PsiClassStub<*> {
|
||||
val classId = firClass.classId
|
||||
val stub = PsiClassStubImpl<ClsClassImpl>(
|
||||
JavaStubElementTypes.CLASS, parent, classId.asSingleFqName().asString(), firClass.name.identifier, null,
|
||||
PsiClassStubImpl.packFlags(
|
||||
false,
|
||||
firClass.classKind == ClassKind.INTERFACE,
|
||||
firClass.classKind == ClassKind.ENUM_CLASS, false, false,
|
||||
firClass.classKind == ClassKind.ANNOTATION_CLASS, false, false,
|
||||
false, false, false
|
||||
)
|
||||
)
|
||||
|
||||
PsiModifierListStubImpl(stub, firClass.packFlags())
|
||||
|
||||
newTypeParameterList(
|
||||
stub,
|
||||
firClass.typeParameters.map { Pair(it.name.asString(), arrayOf(CommonClassNames.JAVA_LANG_OBJECT)) }
|
||||
)
|
||||
|
||||
if (firClass.superTypeRefs.any { it !is FirResolvedTypeRef }) {
|
||||
firClass.setCallbackOnSupertypesComputed {
|
||||
stub.addSupertypesReferencesLists(firClass, session)
|
||||
}
|
||||
} else {
|
||||
stub.addSupertypesReferencesLists(firClass, session)
|
||||
}
|
||||
|
||||
for (nestedClass in firClass.declarations.filterIsInstance<FirRegularClass>()) {
|
||||
buildStub(nestedClass, stub)
|
||||
}
|
||||
|
||||
return stub
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun FirRegularClass.packFlags(): Int {
|
||||
var flags = when (visibility) {
|
||||
Visibilities.PRIVATE -> ModifierFlags.PRIVATE_MASK
|
||||
Visibilities.PROTECTED -> ModifierFlags.PROTECTED_MASK
|
||||
Visibilities.PUBLIC -> ModifierFlags.PUBLIC_MASK
|
||||
else -> ModifierFlags.PACKAGE_LOCAL_MASK
|
||||
}
|
||||
|
||||
flags = flags or when (modality) {
|
||||
Modality.FINAL -> ModifierFlags.FINAL_MASK
|
||||
Modality.ABSTRACT -> ModifierFlags.ABSTRACT_MASK
|
||||
else -> 0
|
||||
}
|
||||
|
||||
if (classId.isNestedClass && !isInner) {
|
||||
flags = flags or ModifierFlags.STATIC_MASK
|
||||
}
|
||||
|
||||
return flags
|
||||
}
|
||||
|
||||
private fun PsiClassStubImpl<*>.addSupertypesReferencesLists(firRegularClass: FirRegularClass, session: FirSession) {
|
||||
require(firRegularClass.superTypeRefs.all { it is FirResolvedTypeRef }) {
|
||||
"Supertypes for light class $qualifiedName are being added too early"
|
||||
}
|
||||
|
||||
val isInterface = firRegularClass.classKind == ClassKind.INTERFACE
|
||||
|
||||
val interfaceNames = mutableListOf<String>()
|
||||
var superName: String? = null
|
||||
|
||||
for (superConeType in firRegularClass.superConeTypes) {
|
||||
val supertypeFirClass = superConeType.toFirClass(session) ?: continue
|
||||
|
||||
val canonicalString = superConeType.mapToCanonicalString(session)
|
||||
|
||||
if (isInterface || supertypeFirClass.classKind == ClassKind.INTERFACE) {
|
||||
interfaceNames.add(canonicalString)
|
||||
} else {
|
||||
superName = canonicalString
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isInterface) {
|
||||
if (interfaceNames.isNotEmpty() && this.isAnnotationType) {
|
||||
interfaceNames.remove(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION)
|
||||
}
|
||||
newReferenceList(JavaStubElementTypes.EXTENDS_LIST, this, ArrayUtil.toStringArray(interfaceNames))
|
||||
newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, this, ArrayUtil.EMPTY_STRING_ARRAY)
|
||||
} else {
|
||||
if (superName == null || "java/lang/Object" == superName || this.isEnum && "java/lang/Enum" == superName) {
|
||||
newReferenceList(JavaStubElementTypes.EXTENDS_LIST, this, ArrayUtil.EMPTY_STRING_ARRAY)
|
||||
} else {
|
||||
newReferenceList(JavaStubElementTypes.EXTENDS_LIST, this, arrayOf(superName))
|
||||
}
|
||||
newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, this, ArrayUtil.toStringArray(interfaceNames))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun newReferenceList(type: JavaClassReferenceListElementType, parent: StubElement<*>, types: Array<String>) {
|
||||
PsiClassReferenceListStubImpl(type, parent, types)
|
||||
}
|
||||
|
||||
private fun newTypeParameterList(parent: StubElement<*>, parameters: List<Pair<String, Array<String>>>) {
|
||||
val listStub = PsiTypeParameterListStubImpl(parent)
|
||||
for (parameter in parameters) {
|
||||
val parameterStub = PsiTypeParameterStubImpl(listStub, parameter.first)
|
||||
newReferenceList(JavaStubElementTypes.EXTENDS_BOUND_LIST, parameterStub, parameter.second)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createJavaFileStub(packageFqName: FqName, files: Collection<KtFile>): PsiJavaFileStub {
|
||||
val javaFileStub = PsiJavaFileStubImpl(packageFqName.asString(), /*compiled = */true)
|
||||
javaFileStub.psiFactory = ClsStubPsiFactory.INSTANCE
|
||||
|
||||
val fakeFile = object : ClsFileImpl(files.first().viewProvider) {
|
||||
override fun getStub() = javaFileStub
|
||||
|
||||
override fun getPackageName() = packageFqName.asString()
|
||||
|
||||
override fun isPhysical() = false
|
||||
|
||||
override fun getText(): String {
|
||||
return files.singleOrNull()?.text ?: super.getText()
|
||||
}
|
||||
}
|
||||
|
||||
javaFileStub.psi = fakeFile
|
||||
return javaFileStub
|
||||
}
|
||||
|
||||
private fun ConeClassLikeType.toFirClass(session: FirSession): FirRegularClass? {
|
||||
return when (this) {
|
||||
is ConeAbbreviatedType -> this.directExpansionType(session)?.toFirClass(session)
|
||||
else -> (this.lookupTag.toSymbol(session) as? FirClassSymbol)?.fir
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// JVM TYPE MAPPING
|
||||
// TODO: reuse other type mapping implementations when possible
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
private const val ERROR_TYPE_STUB = CommonClassNames.JAVA_LANG_OBJECT
|
||||
|
||||
private fun ConeKotlinType.mapToCanonicalString(session: FirSession): String {
|
||||
return when (this) {
|
||||
is ConeClassLikeType -> mapToCanonicalString(session)
|
||||
is ConeTypeParameterType -> lookupTag.name.asString()
|
||||
is ConeTypeVariableType, is ConeFlexibleType, is ConeCapturedType, is ConeDefinitelyNotNullType, is ConeIntersectionType ->
|
||||
error("Unexpected type: $this [${this::class}]")
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeClassLikeType.mapToCanonicalString(session: FirSession): String {
|
||||
return when (this) {
|
||||
is ConeAbbreviatedType -> this.directExpansionType(session)?.mapToCanonicalString(session) ?: ERROR_TYPE_STUB
|
||||
is ConeClassType -> mapToCanonicalString(session)
|
||||
is ConeClassErrorType -> ERROR_TYPE_STUB
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeClassType.mapToCanonicalString(session: FirSession): String {
|
||||
if (lookupTag.classId == StandardClassIds.Array) {
|
||||
return when (val typeProjection = typeArguments[0]) {
|
||||
is ConeStarProjection -> CommonClassNames.JAVA_LANG_OBJECT
|
||||
is ConeTypedProjection -> {
|
||||
if (typeProjection.kind == ProjectionKind.IN)
|
||||
CommonClassNames.JAVA_LANG_VOID
|
||||
else
|
||||
(typeProjection.type as ConeClassLikeType).mapToCanonicalString(session)
|
||||
}
|
||||
else -> ERROR_TYPE_STUB
|
||||
} + "[]"
|
||||
}
|
||||
|
||||
val context = ConeTypeCheckerContext(false, session)
|
||||
|
||||
with(context) {
|
||||
val typeConstructor = typeConstructor()
|
||||
typeConstructor.getPrimitiveType()?.let { return JvmPrimitiveType.get(it).wrapperFqName.asString() }
|
||||
typeConstructor.getPrimitiveArrayType()?.let { return JvmPrimitiveType.get(it).javaKeywordName + "[]" }
|
||||
val kotlinClassFqName = typeConstructor.getClassFqNameUnsafe() ?: return ERROR_TYPE_STUB
|
||||
val mapped = JavaToKotlinClassMap.mapKotlinToJava(kotlinClassFqName)?.asSingleFqName() ?: kotlinClassFqName
|
||||
|
||||
return mapped.toString() +
|
||||
typeArguments.takeIf { it.isNotEmpty() }
|
||||
?.joinToString(separator = ", ", prefix = "<", postfix = ">") { it.mapToCanonicalString(session) }
|
||||
.orEmpty()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun ConeKotlinTypeProjection.mapToCanonicalString(session: FirSession): String {
|
||||
return when (this) {
|
||||
is ConeStarProjection -> "?"
|
||||
is ConeTypedProjection -> {
|
||||
val wildcard = when (kind) {
|
||||
ProjectionKind.STAR -> error("Should be handled in the case above")
|
||||
ProjectionKind.IN -> "? super "
|
||||
ProjectionKind.OUT -> "? extends "
|
||||
ProjectionKind.INVARIANT -> ""
|
||||
}
|
||||
|
||||
wildcard + type.mapToCanonicalString(session)
|
||||
}
|
||||
else -> ERROR_TYPE_STUB
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.java
|
||||
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElementFinder
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
@@ -52,6 +54,10 @@ class FirJavaModuleBasedSession(
|
||||
FirCorrespondingSupertypesCache::class,
|
||||
FirCorrespondingSupertypesCache(this)
|
||||
)
|
||||
|
||||
Extensions.getArea(sessionProvider.project)
|
||||
.getExtensionPoint(PsiElementFinder.EP_NAME)
|
||||
.registerExtension(FirJavaElementFinder(this, sessionProvider.project))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,4 +57,7 @@ class FirJavaClass internal constructor(
|
||||
superTypeRefs.addAll(newSupertypes)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun setCallbackOnSupertypesComputed(callback: () -> Unit) =
|
||||
error("Supertypes computation should happen just before the instance is published")
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
package org.jetbrains.kotlin.fir.resolve
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.service
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class FirProvider : FirSymbolProvider() {
|
||||
abstract fun getFirClassifierByFqName(fqName: ClassId): FirMemberDeclaration?
|
||||
abstract fun getFirClassifierByFqName(fqName: ClassId): FirClassLikeDeclaration<*>?
|
||||
|
||||
abstract override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>?
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.buildDefaultUseSiteScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScope
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
@@ -46,6 +48,10 @@ class FirProviderImpl(val session: FirSession) : FirProvider() {
|
||||
return state.classifierContainerFileMap[fqName] ?: error("Couldn't find container for $fqName")
|
||||
}
|
||||
|
||||
override fun getClassNamesInPackage(fqName: FqName): Set<Name> {
|
||||
return state.classesInPackage[fqName] ?: emptySet()
|
||||
}
|
||||
|
||||
fun recordFile(file: FirFile) {
|
||||
recordFile(file, state)
|
||||
}
|
||||
@@ -64,6 +70,10 @@ class FirProviderImpl(val session: FirSession) : FirProvider() {
|
||||
state.classifierMap[classId] = regularClass
|
||||
state.classifierContainerFileMap[classId] = file
|
||||
|
||||
if (!classId.isNestedClass && !classId.isLocal) {
|
||||
state.classesInPackage.getOrPut(classId.packageFqName, ::mutableSetOf).add(classId.shortClassName)
|
||||
}
|
||||
|
||||
regularClass.acceptChildren(this)
|
||||
}
|
||||
|
||||
@@ -102,6 +112,7 @@ class FirProviderImpl(val session: FirSession) : FirProvider() {
|
||||
val fileMap = mutableMapOf<FqName, List<FirFile>>()
|
||||
val classifierMap = mutableMapOf<ClassId, FirClassLikeDeclaration<*>>()
|
||||
val classifierContainerFileMap = mutableMapOf<ClassId, FirFile>()
|
||||
val classesInPackage = mutableMapOf<FqName, MutableSet<Name>>()
|
||||
val callableMap = mutableMapOf<CallableId, List<FirCallableSymbol<*>>>()
|
||||
val callableContainerMap = mutableMapOf<ConeCallableSymbol, FirFile>()
|
||||
|
||||
@@ -117,6 +128,7 @@ class FirProviderImpl(val session: FirSession) : FirProvider() {
|
||||
classifierContainerFileMap.putAll(other.classifierContainerFileMap)
|
||||
callableMap.putAll(other.callableMap)
|
||||
callableContainerMap.putAll(other.callableContainerMap)
|
||||
classesInPackage.putAll(other.classesInPackage)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -25,6 +25,10 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirTopLevelDeclaredMemberScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.*
|
||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||
@@ -1028,4 +1032,4 @@ internal inline var FirExpression.resultType: FirTypeRef
|
||||
get() = typeRef
|
||||
set(type) {
|
||||
replaceTypeRef(type)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.expandedConeType
|
||||
import org.jetbrains.kotlin.fir.declarations.superConeTypes
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
@@ -17,6 +19,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.ConeTypeVariableTypeConstructor
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.hasNullableSuperType
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.firSafeNullable
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.service
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
@@ -26,13 +29,18 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeAbbreviatedTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||
import org.jetbrains.kotlin.types.checker.convertVariance
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
|
||||
class ErrorTypeConstructor(val reason: String) : TypeConstructorMarker
|
||||
|
||||
interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, TypeCheckerProviderContext {
|
||||
interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, TypeCheckerProviderContext, TypeSystemCommonBackendContext {
|
||||
val session: FirSession
|
||||
|
||||
override fun TypeConstructorMarker.isIntegerLiteralTypeConstructor(): Boolean {
|
||||
@@ -431,6 +439,70 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
||||
return false
|
||||
}
|
||||
|
||||
private fun TypeConstructorMarker.toFirRegularClass(): FirRegularClass? {
|
||||
if (this !is ConeClassLikeSymbol) return null
|
||||
return this.firSafeNullable()
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.isFinalClassOrEnumEntryOrAnnotationClassConstructor(): Boolean {
|
||||
val firRegularClass = toFirRegularClass() ?: return false
|
||||
|
||||
return firRegularClass.modality == Modality.FINAL ||
|
||||
firRegularClass.classKind == ClassKind.ENUM_ENTRY ||
|
||||
firRegularClass.classKind == ClassKind.ANNOTATION_CLASS
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.hasAnnotation(fqName: FqName): Boolean {
|
||||
// TODO support annotations
|
||||
return false
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.getAnnotationFirstArgumentValue(fqName: FqName): Any? {
|
||||
// TODO support annotations
|
||||
return null
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.getTypeParameterClassifier(): TypeParameterMarker? {
|
||||
return this as? FirTypeParameterSymbol
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.isInlineClass(): Boolean {
|
||||
return toFirRegularClass()?.isInline == true
|
||||
}
|
||||
|
||||
override fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker {
|
||||
require(this is ConeTypeParameterSymbol)
|
||||
return this.firSafeNullable<FirTypeParameter>()?.bounds?.getOrNull(0)?.let { (it as? FirResolvedTypeRef)?.type }
|
||||
?: ConeClassTypeImpl(
|
||||
ConeClassLikeLookupTagImpl(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.any.toSafe())), emptyArray(), true
|
||||
)
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? {
|
||||
// TODO: support inline classes
|
||||
return null
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.getPrimitiveType() =
|
||||
getClassFqNameUnsafe()?.let(KotlinBuiltIns.FQ_NAMES.fqNameToPrimitiveType::get)
|
||||
|
||||
override fun TypeConstructorMarker.getPrimitiveArrayType() =
|
||||
getClassFqNameUnsafe()?.let(KotlinBuiltIns.FQ_NAMES.arrayClassFqNameToPrimitiveType::get)
|
||||
|
||||
override fun TypeConstructorMarker.isUnderKotlinPackage() =
|
||||
getClassFqNameUnsafe()?.startsWith(Name.identifier("kotlin")) == true
|
||||
|
||||
override fun TypeConstructorMarker.getClassFqNameUnsafe(): FqNameUnsafe? {
|
||||
return toFirRegularClass()?.symbol?.toLookupTag()?.classId?.asSingleFqName()?.toUnsafe()
|
||||
}
|
||||
|
||||
override fun TypeParameterMarker.getName() = (this as ConeTypeParameterSymbol).name
|
||||
|
||||
override fun KotlinTypeMarker.isInterfaceOrAnnotationClass(): Boolean {
|
||||
val classKind = typeConstructor().toFirRegularClass()?.classKind ?: return false
|
||||
return classKind == ClassKind.ANNOTATION_CLASS || classKind == ClassKind.INTERFACE
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.isError(): Boolean {
|
||||
return this is ErrorTypeConstructor
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// FILE: K1.kt
|
||||
class K2: J1() {
|
||||
fun bar() {
|
||||
foo()
|
||||
baz()
|
||||
|
||||
superClass()
|
||||
superI()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: J1.java
|
||||
public class J1 extends KFirst {
|
||||
void baz() {}
|
||||
}
|
||||
|
||||
// FILE: K2.kt
|
||||
open class KFirst : SuperClass(), SuperI {
|
||||
fun foo() {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: K3.kt
|
||||
abstract class SuperClass {
|
||||
fun superClass() {}
|
||||
}
|
||||
|
||||
interface SuperI {
|
||||
fun superI() {}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
FILE: K1.kt
|
||||
public final class K2 : R|J1| {
|
||||
public constructor(): R|K2| {
|
||||
super<R|J1|>()
|
||||
}
|
||||
|
||||
public final fun bar(): R|kotlin/Unit| {
|
||||
this@R|/KFirst|.R|/KFirst.foo|()
|
||||
this@R|/J1|.R|/J1.baz|()
|
||||
this@R|/SuperClass|.R|/SuperClass.superClass|()
|
||||
this@R|/SuperI|.R|/SuperI.superI|()
|
||||
}
|
||||
|
||||
}
|
||||
FILE: K2.kt
|
||||
public open class KFirst : R|SuperClass|, R|SuperI| {
|
||||
public constructor(): R|KFirst| {
|
||||
super<R|SuperClass|>()
|
||||
}
|
||||
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
FILE: K3.kt
|
||||
public abstract class SuperClass : R|kotlin/Any| {
|
||||
public constructor(): R|SuperClass| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun superClass(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
public abstract interface SuperI : R|kotlin/Any| {
|
||||
public open fun superI(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// FILE: K1.kt
|
||||
class KSub : J1()
|
||||
|
||||
fun main(k: KSub, vString: SuperClass<String>.NestedInSuperClass, vInt: SuperClass<Int>.NestedInSuperClass) {
|
||||
k.getImpl().nestedI(vString)
|
||||
|
||||
// TODO: Support parametrisized inner classes
|
||||
k.getImpl().nestedI(vInt)
|
||||
k.getNestedSubClass().nested("")
|
||||
k.getNestedSubClass().nested(1)
|
||||
}
|
||||
|
||||
// FILE: J1.java
|
||||
public class J1 extends KFirst {
|
||||
|
||||
public class NestedSubClass extends NestedInSuperClass {}
|
||||
public abstract class NestedIImpl implements NestedInI<NestedInSuperClass> {}
|
||||
|
||||
public NestedIImpl getImpl() { return null; }
|
||||
public NestedSubClass getNestedSubClass() { return null; }
|
||||
}
|
||||
|
||||
// FILE: K2.kt
|
||||
open class KFirst : SuperClass<String>(), SuperI<Int>
|
||||
|
||||
// FILE: K3.kt
|
||||
abstract class SuperClass<T> {
|
||||
inner open class NestedInSuperClass {
|
||||
fun nested(x: T) {}
|
||||
}
|
||||
}
|
||||
|
||||
interface SuperI<E> {
|
||||
interface NestedInI<F> {
|
||||
fun nestedI(f: F) {}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
FILE: K1.kt
|
||||
public final class KSub : R|J1| {
|
||||
public constructor(): R|KSub| {
|
||||
super<R|J1|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final fun main(k: R|KSub|, vString: R|SuperClass.NestedInSuperClass<kotlin/String>|, vInt: R|SuperClass.NestedInSuperClass<kotlin/Int>|): R|kotlin/Unit| {
|
||||
R|<local>/k|.R|/J1.getImpl|().R|FakeOverride</SuperI.NestedInI.nestedI: R|kotlin/Unit|>|(R|<local>/vString|)
|
||||
R|<local>/k|.R|/J1.getImpl|().R|FakeOverride</SuperI.NestedInI.nestedI: R|kotlin/Unit|>|(R|<local>/vInt|)
|
||||
R|<local>/k|.R|/J1.getNestedSubClass|().<Inapplicable(INAPPLICABLE): [/SuperClass.NestedInSuperClass.nested]>#(String())
|
||||
R|<local>/k|.R|/J1.getNestedSubClass|().<Inapplicable(INAPPLICABLE): [/SuperClass.NestedInSuperClass.nested]>#(Int(1))
|
||||
}
|
||||
FILE: K2.kt
|
||||
public open class KFirst : R|SuperClass<kotlin/String>|, R|SuperI<kotlin/Int>| {
|
||||
public constructor(): R|KFirst| {
|
||||
super<R|SuperClass<kotlin/String>|>()
|
||||
}
|
||||
|
||||
}
|
||||
FILE: K3.kt
|
||||
public abstract class SuperClass<T> : R|kotlin/Any| {
|
||||
public constructor<T>(): R|SuperClass<T>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public open inner class NestedInSuperClass : R|kotlin/Any| {
|
||||
public constructor(): R|SuperClass.NestedInSuperClass| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun nested(x: R|T|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public abstract interface SuperI<E> : R|kotlin/Any| {
|
||||
public abstract interface NestedInI<F> : R|kotlin/Any| {
|
||||
public open fun nestedI(f: R|F|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// FILE: K1.kt
|
||||
open class KFirst() {
|
||||
fun foo() {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: J1.java
|
||||
public class J1 extends KFirst {
|
||||
void baz() {}
|
||||
}
|
||||
|
||||
// FILE: K2.kt
|
||||
class K2: J1() {
|
||||
fun bar() {
|
||||
foo()
|
||||
baz()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
FILE: K1.kt
|
||||
public open class KFirst : R|kotlin/Any| {
|
||||
public constructor(): R|KFirst| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
FILE: K2.kt
|
||||
public final class K2 : R|J1| {
|
||||
public constructor(): R|K2| {
|
||||
super<R|J1|>()
|
||||
}
|
||||
|
||||
public final fun bar(): R|kotlin/Unit| {
|
||||
this@R|/KFirst|.R|/KFirst.foo|()
|
||||
this@R|/J1|.R|/J1.baz|()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// FILE: K1.kt
|
||||
open class KFirst<T: java.io.Serializable>() {
|
||||
fun foo(t: T): T = t
|
||||
}
|
||||
|
||||
// FILE: J1.java
|
||||
public class J1 extends KFirst<Integer> {
|
||||
void baz() {}
|
||||
}
|
||||
|
||||
// FILE: K2.kt
|
||||
class K2: J1() {
|
||||
fun bar() {
|
||||
foo(1)
|
||||
baz()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
FILE: K1.kt
|
||||
public open class KFirst<T : R|java/io/Serializable|> : R|kotlin/Any| {
|
||||
public constructor<T : R|java/io/Serializable|>(): R|KFirst<T>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun foo(t: R|T|): R|T| {
|
||||
^foo R|<local>/t|
|
||||
}
|
||||
|
||||
}
|
||||
FILE: K2.kt
|
||||
public final class K2 : R|J1| {
|
||||
public constructor(): R|K2| {
|
||||
super<R|J1|>()
|
||||
}
|
||||
|
||||
public final fun bar(): R|kotlin/Unit| {
|
||||
this@R|/KFirst|.R|FakeOverride</KFirst.foo: R|kotlin/Int|>|(Int(1))
|
||||
this@R|/J1|.R|/J1.baz|()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// FILE: K1.kt
|
||||
class KotlinClass
|
||||
|
||||
// FILE: JavaClass.java
|
||||
public class JavaClass {
|
||||
public static void baz(KotlinClass k) {}
|
||||
}
|
||||
|
||||
// FILE: K2.kt
|
||||
fun main() {
|
||||
JavaClass.baz(KotlinClass())
|
||||
JavaClass.baz("")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
FILE: K1.kt
|
||||
public final class KotlinClass : R|kotlin/Any| {
|
||||
public constructor(): R|KotlinClass| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
FILE: K2.kt
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
Q|JavaClass|.R|/JavaClass.baz|(R|/KotlinClass.KotlinClass|())
|
||||
Q|JavaClass|.<Inapplicable(INAPPLICABLE): [/JavaClass.baz]>#(String())
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// FILE: K1.kt
|
||||
class KotlinClass<T>
|
||||
|
||||
// FILE: JavaClass.java
|
||||
public class JavaClass {
|
||||
public static void baz(KotlinClass<Integer> k) {}
|
||||
}
|
||||
|
||||
// FILE: K2.kt
|
||||
fun main() {
|
||||
JavaClass.baz(KotlinClass())
|
||||
JavaClass.baz(KotlinClass<Int>())
|
||||
JavaClass.baz(KotlinClass<String>())
|
||||
JavaClass.baz("")
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
FILE: K1.kt
|
||||
public final class KotlinClass<T> : R|kotlin/Any| {
|
||||
public constructor<T>(): R|KotlinClass<T>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
FILE: K2.kt
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
Q|JavaClass|.R|/JavaClass.baz|(R|/KotlinClass.KotlinClass|<R|ft<kotlin/Int, kotlin/Int?>!|>())
|
||||
Q|JavaClass|.R|/JavaClass.baz|(R|/KotlinClass.KotlinClass|<R|kotlin/Int|>())
|
||||
Q|JavaClass|.<Inapplicable(INAPPLICABLE): [/JavaClass.baz]>#(R|/KotlinClass.KotlinClass|<R|kotlin/String|>())
|
||||
Q|JavaClass|.<Inapplicable(INAPPLICABLE): [/JavaClass.baz]>#(String())
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// FILE: K1.kt
|
||||
open class KotlinOuter {
|
||||
inner open class KotlinInner {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
fun bar() {}
|
||||
}
|
||||
|
||||
// FILE: J1.java
|
||||
public class J1 extends KotlinOuter {
|
||||
public class J2 extends KotlinInner {
|
||||
public void bazbaz() {}
|
||||
}
|
||||
|
||||
public void baz() {}
|
||||
}
|
||||
|
||||
// FILE: K2.kt
|
||||
class K2: J1() {
|
||||
fun main() {
|
||||
bar()
|
||||
baz()
|
||||
}
|
||||
|
||||
inner class K3 : J2() {
|
||||
fun main() {
|
||||
foo()
|
||||
bazbaz()
|
||||
bar()
|
||||
baz()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
FILE: K1.kt
|
||||
public open class KotlinOuter : R|kotlin/Any| {
|
||||
public constructor(): R|KotlinOuter| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public open inner class KotlinInner : R|kotlin/Any| {
|
||||
public constructor(): R|KotlinOuter.KotlinInner| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final fun bar(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
FILE: K2.kt
|
||||
public final class K2 : R|J1| {
|
||||
public constructor(): R|K2| {
|
||||
super<R|J1|>()
|
||||
}
|
||||
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
this@R|/KotlinOuter|.R|/KotlinOuter.bar|()
|
||||
this@R|/J1|.R|/J1.baz|()
|
||||
}
|
||||
|
||||
public final inner class K3 : R|J1.J2| {
|
||||
public constructor(): R|K2.K3| {
|
||||
super<R|J1.J2|>()
|
||||
}
|
||||
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
this@R|/KotlinOuter.KotlinInner|.R|/KotlinOuter.KotlinInner.foo|()
|
||||
this@R|/J1.J2|.R|/J1.J2.bazbaz|()
|
||||
this@R|/KotlinOuter|.R|/KotlinOuter.bar|()
|
||||
this@R|/J1|.R|/J1.baz|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
interface A<T, V : CharSequence>
|
||||
|
||||
class B : A<Int, String>
|
||||
|
||||
// LIGHT_CLASS_FQ_NAME: A, B
|
||||
@@ -0,0 +1,4 @@
|
||||
public interface A <T extends java.lang.Object, V extends java.lang.Object> extends java.lang.Object {
|
||||
}
|
||||
public final class B implements A<java.lang.Integer, java.lang.String> {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
interface A<T>
|
||||
|
||||
class B<E> {
|
||||
inner class C : A<E>
|
||||
class D : A<String>
|
||||
}
|
||||
|
||||
// LIGHT_CLASS_FQ_NAME: B
|
||||
@@ -0,0 +1,7 @@
|
||||
public final class B <E extends java.lang.Object> extends java.lang.Object {
|
||||
public final class C implements A<E> {
|
||||
}
|
||||
|
||||
public static final class D implements A<java.lang.String> {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// FILE: a.kt
|
||||
package a
|
||||
interface A
|
||||
|
||||
// FILE: b.kt
|
||||
package b
|
||||
interface B : a.A
|
||||
|
||||
class C : B
|
||||
|
||||
// LIGHT_CLASS_FQ_NAME: b.B, b.C
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
public interface B extends a.A {
|
||||
}
|
||||
public final class C implements b.B {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
interface A<T>
|
||||
interface Pair<T1, T2>
|
||||
interface Triple<T1, T2, T3>
|
||||
|
||||
class B1 : A<String>
|
||||
class B2 : A<Pair<in String, out String>>
|
||||
class B3 : A<A<*>>
|
||||
class B4 : A<A<String>>
|
||||
class B5 : A<List<A<*>>>
|
||||
class B6 : A<Int>
|
||||
class B7 : A<IntArray>
|
||||
class B8 : A<Array<String>>
|
||||
class B9 : A<Array<Int>>
|
||||
class B10 : A<Array<IntArray>>
|
||||
|
||||
// LIGHT_CLASS_FQ_NAME: B1, B2, B3, B4, B5, B6, B7, B8, B9, B10
|
||||
@@ -0,0 +1,20 @@
|
||||
public final class B1 implements A<java.lang.String> {
|
||||
}
|
||||
public final class B2 implements A<Pair<? super java.lang.String, ? extends java.lang.String>> {
|
||||
}
|
||||
public final class B3 implements A<A<?>> {
|
||||
}
|
||||
public final class B4 implements A<A<java.lang.String>> {
|
||||
}
|
||||
public final class B5 implements A<java.util.List<A<?>>> {
|
||||
}
|
||||
public final class B6 implements A<java.lang.Integer> {
|
||||
}
|
||||
public final class B7 implements A<int[]> {
|
||||
}
|
||||
public final class B8 implements A<java.lang.String[]> {
|
||||
}
|
||||
public final class B9 implements A<java.lang.Integer[]> {
|
||||
}
|
||||
public final class B10 implements A<int[][]> {
|
||||
}
|
||||
+10
-5
@@ -22,11 +22,8 @@ import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.CommonPlatforms
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.js.JsPlatforms
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.platform.konan.KonanPlatforms
|
||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
||||
import java.io.File
|
||||
@@ -35,7 +32,7 @@ import java.util.*
|
||||
abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() {
|
||||
override fun analyzeAndCheck(testDataFile: File, files: List<TestFile>) {
|
||||
try {
|
||||
analyzeAndCheckUnhandled(files)
|
||||
analyzeAndCheckUnhandled(testDataFile, files)
|
||||
} catch (t: AssertionError) {
|
||||
throw t
|
||||
} catch (t: Throwable) {
|
||||
@@ -52,7 +49,7 @@ abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun analyzeAndCheckUnhandled(files: List<TestFile>) {
|
||||
protected open fun analyzeAndCheckUnhandled(testDataFile: File, files: List<TestFile>) {
|
||||
val groupedByModule = files.groupBy(TestFile::module)
|
||||
|
||||
val modules = createModules(groupedByModule)
|
||||
@@ -93,6 +90,14 @@ abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() {
|
||||
|
||||
doFirResolveTestBench(firFiles, FirTotalResolveTransformer().transformers, gc = false)
|
||||
|
||||
checkResultingFirFiles(firFiles, testDataFile)
|
||||
}
|
||||
|
||||
protected open fun checkResultingFirFiles(
|
||||
firFiles: MutableList<FirFile>,
|
||||
testDataFile: File
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.fir
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractFirDiagnosticsTest : AbstractFirDiagnosticsSmokeTest() {
|
||||
|
||||
override fun checkResultingFirFiles(
|
||||
firFiles: MutableList<FirFile>,
|
||||
testDataFile: File
|
||||
) {
|
||||
val firFileDump = StringBuilder().also { stringBuilder ->
|
||||
firFiles.map {
|
||||
it.accept(FirRenderer(stringBuilder), null)
|
||||
}
|
||||
}.toString()
|
||||
val expectedPath = testDataFile.path.replace(".kt", ".txt")
|
||||
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump)
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.fir;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("compiler/fir/resolve/testData/diagnostics")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInDiagnostics() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/resolve/testData/diagnostics/j+k")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class J_k extends AbstractFirDiagnosticsTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJ_k() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/diagnostics/j+k"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("KJKComplexHierarchy.kt")
|
||||
public void testKJKComplexHierarchy() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/j+k/KJKComplexHierarchy.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("KJKComplexHierarchyWithNested.kt")
|
||||
public void testKJKComplexHierarchyWithNested() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/j+k/KJKComplexHierarchyWithNested.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("KJKInheritance.kt")
|
||||
public void testKJKInheritance() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/j+k/KJKInheritance.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("KJKInheritanceGeneric.kt")
|
||||
public void testKJKInheritanceGeneric() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/j+k/KJKInheritanceGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("KotlinClassParameter.kt")
|
||||
public void testKotlinClassParameter() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/j+k/KotlinClassParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("KotlinClassParameterGeneric.kt")
|
||||
public void testKotlinClassParameterGeneric() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/j+k/KotlinClassParameterGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("outerInnerClasses.kt")
|
||||
public void testOuterInnerClasses() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/j+k/outerInnerClasses.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.fir.java
|
||||
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.psi.PsiElementFinder
|
||||
import com.intellij.psi.impl.compiled.ClsClassImpl
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.fir.AbstractFirDiagnosticsSmokeTest
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractFirLightClassesTest : AbstractFirDiagnosticsSmokeTest() {
|
||||
override fun checkResultingFirFiles(firFiles: MutableList<FirFile>, testDataFile: File) {
|
||||
super.checkResultingFirFiles(firFiles, testDataFile)
|
||||
|
||||
val ourFinders =
|
||||
Extensions.getArea(project).getExtensionPoint(PsiElementFinder.EP_NAME).extensions.filterIsInstance<FirJavaElementFinder>()
|
||||
|
||||
assertNotEmpty(ourFinders)
|
||||
|
||||
val stringBuilder = StringBuilder()
|
||||
|
||||
for (qualifiedName in InTextDirectivesUtils.findListWithPrefixes(testDataFile.readText(), "// LIGHT_CLASS_FQ_NAME: ")) {
|
||||
val fqName = FqName(qualifiedName)
|
||||
val packageName = fqName.parent().asString()
|
||||
|
||||
val ourFinder = ourFinders.firstOrNull { finder -> finder.findPackage(packageName) != null }
|
||||
assertNotNull("PsiPackage for ${fqName.parent()} was not found", ourFinder)
|
||||
ourFinder!!
|
||||
|
||||
val psiPackage = ourFinder.findPackage(fqName.parent().asString())
|
||||
assertNotNull("PsiPackage for ${fqName.parent()} is null", psiPackage)
|
||||
|
||||
val psiClass = assertInstanceOf(
|
||||
ourFinder.findClass(qualifiedName, GlobalSearchScope.allScope(project)),
|
||||
ClsClassImpl::class.java
|
||||
)
|
||||
|
||||
psiClass.appendMirrorText(0, stringBuilder)
|
||||
stringBuilder.appendln()
|
||||
}
|
||||
|
||||
val expectedPath = testDataFile.path.replace(".kt", ".txt")
|
||||
KotlinTestUtils.assertEqualsToFile(File(expectedPath), stringBuilder.toString())
|
||||
}
|
||||
}
|
||||
Generated
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.fir.java;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("compiler/fir/resolve/testData/lightClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class FirLightClassesTestGenerated extends AbstractFirLightClassesTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInLightClasses() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/lightClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("genericClasses.kt")
|
||||
public void testGenericClasses() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/lightClasses/genericClasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedClasses.kt")
|
||||
public void testNestedClasses() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/lightClasses/nestedClasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/lightClasses/simple.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeMapping.kt")
|
||||
public void testTypeMapping() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/lightClasses/typeMapping.kt");
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,8 @@ interface FirRegularClass : FirClass, @VisitedSupertype FirClassLikeDeclaration<
|
||||
}
|
||||
|
||||
fun replaceSupertypes(newSupertypes: List<FirTypeRef>): FirRegularClass
|
||||
|
||||
fun setCallbackOnSupertypesComputed(callback: () -> Unit)
|
||||
}
|
||||
|
||||
val FirRegularClass.classId get() = symbol.classId
|
||||
|
||||
@@ -63,6 +63,8 @@ open class FirClassImpl(
|
||||
override fun replaceSupertypes(newSupertypes: List<FirTypeRef>): FirRegularClass {
|
||||
superTypeRefs.clear()
|
||||
superTypeRefs.addAll(newSupertypes)
|
||||
callbackOnSupertypesComputed?.invoke()
|
||||
callbackOnSupertypesComputed = null
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -76,4 +78,10 @@ open class FirClassImpl(
|
||||
companionObject = declarations.asSequence().filterIsInstance<FirRegularClass>().firstOrNull { it.isCompanion }
|
||||
return result
|
||||
}
|
||||
|
||||
private var callbackOnSupertypesComputed: (() -> Unit)? = null
|
||||
|
||||
override fun setCallbackOnSupertypesComputed(callback: () -> Unit) {
|
||||
callbackOnSupertypesComputed = callback
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -54,9 +54,17 @@ class FirEnumEntryImpl(
|
||||
override fun replaceSupertypes(newSupertypes: List<FirTypeRef>): FirRegularClass {
|
||||
superTypeRefs.clear()
|
||||
superTypeRefs.addAll(newSupertypes)
|
||||
callbackOnSupertypesComputed?.invoke()
|
||||
callbackOnSupertypesComputed = null
|
||||
return this
|
||||
}
|
||||
|
||||
private var callbackOnSupertypesComputed: (() -> Unit)? = null
|
||||
|
||||
override fun setCallbackOnSupertypesComputed(callback: () -> Unit) {
|
||||
callbackOnSupertypesComputed = callback
|
||||
}
|
||||
|
||||
override fun replaceTypeRef(newTypeRef: FirTypeRef) {
|
||||
typeRef = newTypeRef
|
||||
}
|
||||
@@ -85,4 +93,4 @@ class FirEnumEntryImpl(
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.codegen.flags.AbstractWriteFlagsTest
|
||||
import org.jetbrains.kotlin.codegen.ir.*
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.builder.AbstractRawFirBuilderTestCase
|
||||
import org.jetbrains.kotlin.fir.java.AbstractFirLightClassesTest
|
||||
import org.jetbrains.kotlin.fir.java.AbstractFirTypeEnhancementTest
|
||||
import org.jetbrains.kotlin.fir.java.AbstractOwnFirTypeEnhancementTest
|
||||
import org.jetbrains.kotlin.generators.tests.generator.testGroup
|
||||
@@ -487,6 +488,19 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("compiler/fir/resolve/tests", "compiler/fir/resolve/testData") {
|
||||
|
||||
testClass<AbstractFirDiagnosticsTest> {
|
||||
model("diagnostics")
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("compiler/fir/resolve/tests", "compiler/fir/resolve/testData") {
|
||||
testClass<AbstractFirLightClassesTest> {
|
||||
model("lightClasses")
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("compiler/fir/fir2ir/tests", "compiler/testData") {
|
||||
testClass<AbstractFir2IrTextTest> {
|
||||
model("ir/irText")
|
||||
|
||||
Reference in New Issue
Block a user