[FIR] Implement early calculation of "not SAM" flag for classes

This commit is contained in:
Mikhail Glukhikh
2020-01-24 13:47:21 +03:00
parent 279adae3e4
commit dc4f332c08
10 changed files with 50 additions and 13 deletions
@@ -11,29 +11,22 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.addDefaultBoundIfNecessary
import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl
import org.jetbrains.kotlin.fir.declarations.visibility
import org.jetbrains.kotlin.fir.generateValueOfFunction
import org.jetbrains.kotlin.fir.generateValuesFunction
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.java.declarations.FirJavaConstructor
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope
import org.jetbrains.kotlin.fir.java.scopes.JavaClassUseSiteMemberScope
import org.jetbrains.kotlin.fir.java.scopes.JavaOverrideChecker
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.toFirSourceElement
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.load.java.JavaClassFinder
@@ -257,6 +250,7 @@ class JavaSymbolProvider(
generateValuesFunction(session, classId.packageFqName, classId.relativeClassName)
generateValueOfFunction(session, classId.packageFqName, classId.relativeClassName)
}
calculateSAM()
}
}
}
@@ -456,6 +456,7 @@ class DeclarationsConverter(
firClass.generateValuesFunction(session, context.packageFqName, context.className)
firClass.generateValueOfFunction(session, context.packageFqName, context.className)
}
firClass.calculateSAM()
return@withChildClassName firClass
}
@@ -618,6 +618,7 @@ class RawFirBuilder(session: FirSession, val scopeProvider: FirScopeProvider, va
firClass.generateValuesFunction(session, context.packageFqName, context.className)
firClass.generateValueOfFunction(session, context.packageFqName, context.className)
}
firClass.calculateSAM()
firClass
}
@@ -5,10 +5,10 @@
package org.jetbrains.kotlin.fir.deserialization
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.calculateSAM
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.addDeclarations
import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirEnumEntryImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirSealedClassImpl
import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider
import org.jetbrains.kotlin.fir.declarations.impl.*
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
@@ -150,4 +149,5 @@ fun deserializeClassToSymbol(
}
}
}
firClass.calculateSAM()
}
@@ -244,6 +244,8 @@ private fun FirRegularClass.findSingleAbstractMethodByNames(
scopeSession: ScopeSession,
samCandidateNames: Set<Name>
): FirSimpleFunction? {
if (status.isNotSAM) return null
var resultMethod: FirSimpleFunction? = null
var metIncorrectMember = false
@@ -35,6 +35,7 @@ interface FirDeclarationStatus : FirElement {
val isData: Boolean
val isSuspend: Boolean
val isStatic: Boolean
val isNotSAM: Boolean
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitDeclarationStatus(this, data)
}
@@ -34,6 +34,7 @@ interface FirResolvedDeclarationStatus : FirDeclarationStatus {
override val isData: Boolean
override val isSuspend: Boolean
override val isStatic: Boolean
override val isNotSAM: Boolean
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitResolvedDeclarationStatus(this, data)
}
@@ -6,11 +6,17 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirModifiableClass
import org.jetbrains.kotlin.fir.declarations.modality
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression
import org.jetbrains.kotlin.fir.visitors.FirTransformer
fun ModuleInfo.dependenciesWithoutSelf(): Sequence<ModuleInfo> = dependencies().asSequence().filter { it != this }
@@ -30,4 +36,27 @@ tailrec fun FirElement.unwrapSmartcast(): FirElement = if (this is FirExpression
originalExpression.unwrapSmartcast()
} else {
this
}
private val PUBLIC_METHOD_NAMES_IN_OBJECT = setOf("equals", "hashCode", "getClass", "wait", "notify", "notifyAll", "toString")
fun FirModifiableClass<FirRegularClass>.calculateSAM() {
val status = symbol.fir.status as FirDeclarationStatusImpl
var counter = 0
for (declaration in declarations) {
if (declaration is FirProperty && declaration.modality == Modality.ABSTRACT) {
status.isNotSAM = true
return
}
if (declaration is FirSimpleFunction) {
if (declaration.modality != Modality.ABSTRACT || declaration.name.asString() in PUBLIC_METHOD_NAMES_IN_OBJECT) {
continue
}
counter++
if (counter > 1) {
status.isNotSAM = true
return
}
}
}
}
@@ -121,6 +121,12 @@ open class FirDeclarationStatusImpl(
this[STATIC] = value
}
override var isNotSAM: Boolean
get() = this[NOT_SAM]
set(value) {
this[NOT_SAM] = value
}
private enum class Modifier(val mask: Int) {
EXPECT(0x1),
ACTUAL(0x2),
@@ -136,7 +142,8 @@ open class FirDeclarationStatusImpl(
COMPANION(0x800),
DATA(0x1000),
SUSPEND(0x2000),
STATIC(0x4000)
STATIC(0x4000),
NOT_SAM(0x8000)
}
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
@@ -302,7 +302,8 @@ object NodeConfigurator : AbstractFieldConfigurator() {
+modality
generateBooleanFields(
"expect", "actual", "override", "operator", "infix", "inline", "tailRec",
"external", "const", "lateInit", "inner", "companion", "data", "suspend", "static"
"external", "const", "lateInit", "inner", "companion", "data", "suspend",
"static", "notSAM"
)
}