[FIR] Introduce DeclarationPredicates for matching declarations for extensions
This commit is contained in:
@@ -98,6 +98,7 @@ class FirExtensionsService(
|
|||||||
require(annotation.classKind == ClassKind.ANNOTATION_CLASS)
|
require(annotation.classKind == ClassKind.ANNOTATION_CLASS)
|
||||||
val fqName = annotation.symbol.classId.asSingleFqName()
|
val fqName = annotation.symbol.classId.asSingleFqName()
|
||||||
_annotations += fqName
|
_annotations += fqName
|
||||||
|
userDefinedAnnotations.put(metaAnnotation, fqName)
|
||||||
val extensions = extensionsWithMetaAnnotations[metaAnnotation]
|
val extensions = extensionsWithMetaAnnotations[metaAnnotation]
|
||||||
if (extensions.isEmpty()) return
|
if (extensions.isEmpty()) return
|
||||||
for (extension in extensions) {
|
for (extension in extensions) {
|
||||||
@@ -128,6 +129,9 @@ class FirExtensionsService(
|
|||||||
|
|
||||||
private val extensionsWithMetaAnnotations: Multimap<AnnotationFqn, FirExtension> = createMultimap()
|
private val extensionsWithMetaAnnotations: Multimap<AnnotationFqn, FirExtension> = createMultimap()
|
||||||
|
|
||||||
|
// MetaAnnotation -> Annotations
|
||||||
|
val userDefinedAnnotations: Multimap<AnnotationFqn, AnnotationFqn> = createMultimap()
|
||||||
|
|
||||||
var registeredExtensionsSize: Int = 0
|
var registeredExtensionsSize: Int = 0
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
|||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.predicate
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
|
||||||
|
|
||||||
|
// -------------------------------------------- Predicates --------------------------------------------
|
||||||
|
|
||||||
|
sealed class DeclarationPredicate {
|
||||||
|
abstract val annotations: Set<AnnotationFqn>
|
||||||
|
abstract val metaAnnotations: Set<AnnotationFqn>
|
||||||
|
|
||||||
|
internal abstract fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R
|
||||||
|
|
||||||
|
object Any : DeclarationPredicate() {
|
||||||
|
override val annotations: Set<AnnotationFqn>
|
||||||
|
get() = emptySet()
|
||||||
|
override val metaAnnotations: Set<AnnotationFqn>
|
||||||
|
get() = emptySet()
|
||||||
|
|
||||||
|
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitAny(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Or(val a: DeclarationPredicate, val b: DeclarationPredicate) : DeclarationPredicate() {
|
||||||
|
override val annotations: Set<AnnotationFqn> = a.annotations + b.annotations
|
||||||
|
override val metaAnnotations: Set<AnnotationFqn> = a.metaAnnotations + b.metaAnnotations
|
||||||
|
|
||||||
|
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitOr(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class And(val a: DeclarationPredicate, val b: DeclarationPredicate) : DeclarationPredicate() {
|
||||||
|
override val annotations: Set<AnnotationFqn> = a.annotations + b.annotations
|
||||||
|
override val metaAnnotations: Set<AnnotationFqn> = a.metaAnnotations + b.metaAnnotations
|
||||||
|
|
||||||
|
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitAnd(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class Annotated(final override val annotations: Set<AnnotationFqn>) : DeclarationPredicate() {
|
||||||
|
init {
|
||||||
|
require(annotations.isNotEmpty()) {
|
||||||
|
"Annotations should be not empty"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final override val metaAnnotations: Set<AnnotationFqn>
|
||||||
|
get() = emptySet()
|
||||||
|
|
||||||
|
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitAnnotated(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations) {
|
||||||
|
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitAnnotatedWith(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnderAnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations) {
|
||||||
|
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitUnderAnnotatedWith(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class MetaAnnotated(final override val metaAnnotations: Set<AnnotationFqn>) : DeclarationPredicate() {
|
||||||
|
init {
|
||||||
|
require(metaAnnotations.isNotEmpty()) {
|
||||||
|
"Annotations should be not empty"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final override val annotations: Set<AnnotationFqn>
|
||||||
|
get() = emptySet()
|
||||||
|
|
||||||
|
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitMetaAnnotated(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnnotatedWithMeta(metaAnnotations: Set<AnnotationFqn>) : MetaAnnotated(metaAnnotations) {
|
||||||
|
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitAnnotatedWithMeta(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnderMetaAnnotated(metaAnnotations: Set<AnnotationFqn>) : MetaAnnotated(metaAnnotations) {
|
||||||
|
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitUnderMetaAnnotated(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------- DSL --------------------------------------------
|
||||||
|
|
||||||
|
infix fun DeclarationPredicate.or(other: DeclarationPredicate): DeclarationPredicate = DeclarationPredicate.Or(this, other)
|
||||||
|
infix fun DeclarationPredicate.and(other: DeclarationPredicate): DeclarationPredicate = DeclarationPredicate.And(this, other)
|
||||||
|
|
||||||
|
fun under(vararg annotations: AnnotationFqn): DeclarationPredicate = UnderAnnotatedWith(annotations.toSet())
|
||||||
|
fun has(vararg annotations: AnnotationFqn): DeclarationPredicate = AnnotatedWith(annotations.toSet())
|
||||||
|
fun metaUnder(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate = AnnotatedWithMeta(metaAnnotations.toSet())
|
||||||
|
fun metaHas(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate = UnderMetaAnnotated(metaAnnotations.toSet())
|
||||||
|
|
||||||
|
fun hasOrUnder(vararg annotations: AnnotationFqn): DeclarationPredicate = has(*annotations) or under(*annotations)
|
||||||
|
fun metaHasOrUnder(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate = metaHas(*metaAnnotations) or metaUnder(*metaAnnotations)
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.predicate
|
||||||
|
|
||||||
|
internal abstract class DeclarationPredicateVisitor<R, D> {
|
||||||
|
abstract fun visitPredicate(predicate: DeclarationPredicate, data: D): R
|
||||||
|
open fun visitAny(predicate: DeclarationPredicate.Any, data: D): R {
|
||||||
|
return visitPredicate(predicate, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitAnd(predicate: DeclarationPredicate.And, data: D): R {
|
||||||
|
return visitPredicate(predicate, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitOr(predicate: DeclarationPredicate.Or, data: D): R {
|
||||||
|
return visitPredicate(predicate, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitAnnotated(predicate: Annotated, data: D): R {
|
||||||
|
return visitPredicate(predicate, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitAnnotatedWith(predicate: AnnotatedWith, data: D): R {
|
||||||
|
return visitAnnotated(predicate, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitUnderAnnotatedWith(predicate: UnderAnnotatedWith, data: D): R {
|
||||||
|
return visitAnnotated(predicate, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitMetaAnnotated(predicate: MetaAnnotated, data: D): R {
|
||||||
|
return visitPredicate(predicate, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitAnnotatedWithMeta(predicate: AnnotatedWithMeta, data: D): R {
|
||||||
|
return visitMetaAnnotated(predicate, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitUnderMetaAnnotated(predicate: UnderMetaAnnotated, data: D): R {
|
||||||
|
return visitMetaAnnotated(predicate, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user