From 8acb8aa04329160e3dc8c3976c2bc480e8c89118 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Fri, 20 May 2022 11:56:53 +0300 Subject: [PATCH] [FIR] Introduce utility service for plugins for matching common predicate pattern --- ...ractSimpleClassPredicateMatchingService.kt | 45 ++++++++++++++ .../fir/FirAllOpenExtensionRegistrar.kt | 3 +- .../fir/FirAllOpenStatusTransformer.kt | 58 ++++++++----------- 3 files changed, 70 insertions(+), 36 deletions(-) create mode 100644 compiler/fir/providers/src/org/jetbrains/kotlin/fir/extensions/utils/AbstractSimpleClassPredicateMatchingService.kt diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/extensions/utils/AbstractSimpleClassPredicateMatchingService.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/extensions/utils/AbstractSimpleClassPredicateMatchingService.kt new file mode 100644 index 00000000000..6042e28e0c7 --- /dev/null +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/extensions/utils/AbstractSimpleClassPredicateMatchingService.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2022 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.extensions.utils + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.caches.FirCache +import org.jetbrains.kotlin.fir.caches.firCachesFactory +import org.jetbrains.kotlin.fir.caches.getValue +import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar +import org.jetbrains.kotlin.fir.extensions.FirExtensionSessionComponent +import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate +import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.types.toRegularClassSymbol + +/** + * Utility base class for services which may quickly answer to question + * "is this class or some of its superclasses matches specific predicate or not?" + */ +abstract class AbstractSimpleClassPredicateMatchingService(session: FirSession) : FirExtensionSessionComponent(session) { + protected abstract val predicate: DeclarationPredicate + + final override fun FirDeclarationPredicateRegistrar.registerPredicates() { + register(predicate) + } + + fun isAnnotated(symbol: FirRegularClassSymbol): Boolean { + return cache.getValue(symbol) + } + + private val cache: FirCache = session.firCachesFactory.createCache { symbol, _ -> + symbol.annotated() + } + + private fun FirRegularClassSymbol.annotated(): Boolean { + if (session.predicateBasedProvider.matches(predicate, this)) return true + return resolvedSuperTypes.any { + val superSymbol = it.toRegularClassSymbol(session) ?: return@any false + cache.getValue(superSymbol) + } + } +} diff --git a/plugins/allopen/allopen.k2/src/org/jetbrains/kotlin/allopen/fir/FirAllOpenExtensionRegistrar.kt b/plugins/allopen/allopen.k2/src/org/jetbrains/kotlin/allopen/fir/FirAllOpenExtensionRegistrar.kt index cf53e2279ac..eaebb33140a 100644 --- a/plugins/allopen/allopen.k2/src/org/jetbrains/kotlin/allopen/fir/FirAllOpenExtensionRegistrar.kt +++ b/plugins/allopen/allopen.k2/src/org/jetbrains/kotlin/allopen/fir/FirAllOpenExtensionRegistrar.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar class FirAllOpenExtensionRegistrar(val allOpenAnnotationFqNames: List) : FirExtensionRegistrar() { override fun ExtensionRegistrarContext.configurePlugin() { - +FirAllOpenStatusTransformer.getFactory(allOpenAnnotationFqNames) + +::FirAllOpenStatusTransformer + +FirAllOpenPredicateMatcher.getFactory(allOpenAnnotationFqNames) } } diff --git a/plugins/allopen/allopen.k2/src/org/jetbrains/kotlin/allopen/fir/FirAllOpenStatusTransformer.kt b/plugins/allopen/allopen.k2/src/org/jetbrains/kotlin/allopen/fir/FirAllOpenStatusTransformer.kt index 64ca3b29fb9..b26924ee934 100644 --- a/plugins/allopen/allopen.k2/src/org/jetbrains/kotlin/allopen/fir/FirAllOpenStatusTransformer.kt +++ b/plugins/allopen/allopen.k2/src/org/jetbrains/kotlin/allopen/fir/FirAllOpenStatusTransformer.kt @@ -8,66 +8,36 @@ package org.jetbrains.kotlin.allopen.fir import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.caches.FirCache -import org.jetbrains.kotlin.fir.caches.firCachesFactory -import org.jetbrains.kotlin.fir.caches.getValue import org.jetbrains.kotlin.fir.copy import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar +import org.jetbrains.kotlin.fir.extensions.FirExtensionSessionComponent.Factory import org.jetbrains.kotlin.fir.extensions.FirStatusTransformerExtension -import org.jetbrains.kotlin.fir.extensions.FirStatusTransformerExtension.Factory import org.jetbrains.kotlin.fir.extensions.predicate.has import org.jetbrains.kotlin.fir.extensions.predicate.metaHas import org.jetbrains.kotlin.fir.extensions.predicate.or -import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider +import org.jetbrains.kotlin.fir.extensions.utils.AbstractSimpleClassPredicateMatchingService import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol -import org.jetbrains.kotlin.fir.types.toRegularClassSymbol import org.jetbrains.kotlin.name.FqName -class FirAllOpenStatusTransformer(allOpenAnnotationFqNames: List, session: FirSession) : FirStatusTransformerExtension(session) { - companion object { - fun getFactory(allOpenAnnotationFqNames: List): Factory { - return Factory { session -> FirAllOpenStatusTransformer(allOpenAnnotationFqNames, session) } - } - } - - private val annotationFqNames = allOpenAnnotationFqNames.map { FqName(it) } - private val hasPredicate = has(annotationFqNames) or metaHas(annotationFqNames) - - private val cache: FirCache = session.firCachesFactory.createCache { symbol, _ -> - symbol.annotated() - } - - override fun FirDeclarationPredicateRegistrar.registerPredicates() { - register(hasPredicate) - } - +class FirAllOpenStatusTransformer(session: FirSession) : FirStatusTransformerExtension(session) { override fun needTransformStatus(declaration: FirDeclaration): Boolean { return when (declaration) { - is FirRegularClass -> declaration.classKind == ClassKind.CLASS && cache.getValue(declaration.symbol) + is FirRegularClass -> declaration.classKind == ClassKind.CLASS && session.allOpenPredicateMatcher.isAnnotated(declaration.symbol) is FirCallableDeclaration -> { val parentClassId = declaration.symbol.callableId.classId ?: return false if (parentClassId.isLocal) return false val parentClassSymbol = session.symbolProvider.getClassLikeSymbolByClassId(parentClassId) as? FirRegularClassSymbol ?: return false - cache.getValue(parentClassSymbol) + session.allOpenPredicateMatcher.isAnnotated(parentClassSymbol) } else -> false } } - private fun FirRegularClassSymbol.annotated(): Boolean { - if (session.predicateBasedProvider.matches(hasPredicate, this)) return true - return resolvedSuperTypes.any { - val superSymbol = it.toRegularClassSymbol(session) ?: return@any false - cache.getValue(superSymbol) - } - } - override fun transformStatus(status: FirDeclarationStatus, declaration: FirDeclaration): FirDeclarationStatus { return if (status.modality == null) { status.copy(modality = Modality.OPEN) @@ -76,3 +46,21 @@ class FirAllOpenStatusTransformer(allOpenAnnotationFqNames: List, sessio } } } + +class FirAllOpenPredicateMatcher( + session: FirSession, + allOpenAnnotationFqNames: List +) : AbstractSimpleClassPredicateMatchingService(session) { + companion object { + fun getFactory(allOpenAnnotationFqNames: List): Factory { + return Factory { session -> FirAllOpenPredicateMatcher(session, allOpenAnnotationFqNames) } + } + } + + override val predicate = run { + val annotationFqNames = allOpenAnnotationFqNames.map { FqName(it) } + has(annotationFqNames) or metaHas(annotationFqNames) + } +} + +val FirSession.allOpenPredicateMatcher: FirAllOpenPredicateMatcher by FirSession.sessionComponentAccessor()