[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 com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibility 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.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.addDefaultBoundIfNecessary import org.jetbrains.kotlin.fir.declarations.addDefaultBoundIfNecessary
import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl
import org.jetbrains.kotlin.fir.declarations.visibility 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.FirJavaClass
import org.jetbrains.kotlin.fir.java.declarations.FirJavaConstructor import org.jetbrains.kotlin.fir.java.declarations.FirJavaConstructor
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod 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.*
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.* import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.* 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.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.load.java.JavaClassFinder import org.jetbrains.kotlin.load.java.JavaClassFinder
@@ -257,6 +250,7 @@ class JavaSymbolProvider(
generateValuesFunction(session, classId.packageFqName, classId.relativeClassName) generateValuesFunction(session, classId.packageFqName, classId.relativeClassName)
generateValueOfFunction(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.generateValuesFunction(session, context.packageFqName, context.className)
firClass.generateValueOfFunction(session, context.packageFqName, context.className) firClass.generateValueOfFunction(session, context.packageFqName, context.className)
} }
firClass.calculateSAM()
return@withChildClassName firClass return@withChildClassName firClass
} }
@@ -618,6 +618,7 @@ class RawFirBuilder(session: FirSession, val scopeProvider: FirScopeProvider, va
firClass.generateValuesFunction(session, context.packageFqName, context.className) firClass.generateValuesFunction(session, context.packageFqName, context.className)
firClass.generateValueOfFunction(session, context.packageFqName, context.className) firClass.generateValueOfFunction(session, context.packageFqName, context.className)
} }
firClass.calculateSAM()
firClass firClass
} }
@@ -5,10 +5,10 @@
package org.jetbrains.kotlin.fir.deserialization package org.jetbrains.kotlin.fir.deserialization
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession 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.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.addDeclarations import org.jetbrains.kotlin.fir.declarations.addDeclarations
import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl 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.FirEnumEntryImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirSealedClassImpl import org.jetbrains.kotlin.fir.declarations.impl.FirSealedClassImpl
import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider 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.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl 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, scopeSession: ScopeSession,
samCandidateNames: Set<Name> samCandidateNames: Set<Name>
): FirSimpleFunction? { ): FirSimpleFunction? {
if (status.isNotSAM) return null
var resultMethod: FirSimpleFunction? = null var resultMethod: FirSimpleFunction? = null
var metIncorrectMember = false var metIncorrectMember = false
@@ -35,6 +35,7 @@ interface FirDeclarationStatus : FirElement {
val isData: Boolean val isData: Boolean
val isSuspend: Boolean val isSuspend: Boolean
val isStatic: Boolean val isStatic: Boolean
val isNotSAM: Boolean
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitDeclarationStatus(this, data) 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 isData: Boolean
override val isSuspend: Boolean override val isSuspend: Boolean
override val isStatic: 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) 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 package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.analyzer.ModuleInfo 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.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression
import org.jetbrains.kotlin.fir.visitors.FirTransformer
fun ModuleInfo.dependenciesWithoutSelf(): Sequence<ModuleInfo> = dependencies().asSequence().filter { it != this } 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() originalExpression.unwrapSmartcast()
} else { } else {
this 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 this[STATIC] = value
} }
override var isNotSAM: Boolean
get() = this[NOT_SAM]
set(value) {
this[NOT_SAM] = value
}
private enum class Modifier(val mask: Int) { private enum class Modifier(val mask: Int) {
EXPECT(0x1), EXPECT(0x1),
ACTUAL(0x2), ACTUAL(0x2),
@@ -136,7 +142,8 @@ open class FirDeclarationStatusImpl(
COMPANION(0x800), COMPANION(0x800),
DATA(0x1000), DATA(0x1000),
SUSPEND(0x2000), SUSPEND(0x2000),
STATIC(0x4000) STATIC(0x4000),
NOT_SAM(0x8000)
} }
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {} override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
@@ -302,7 +302,8 @@ object NodeConfigurator : AbstractFieldConfigurator() {
+modality +modality
generateBooleanFields( generateBooleanFields(
"expect", "actual", "override", "operator", "infix", "inline", "tailRec", "expect", "actual", "override", "operator", "infix", "inline", "tailRec",
"external", "const", "lateInit", "inner", "companion", "data", "suspend", "static" "external", "const", "lateInit", "inner", "companion", "data", "suspend",
"static", "notSAM"
) )
} }