From f3d4fa715e949101799dfa46911de470feff66fa Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Tue, 12 May 2020 13:20:37 +0300 Subject: [PATCH] [FIR] Introduce DeclarationPredicates for matching declarations for extensions --- .../fir/extensions/FirExtensionsService.kt | 4 + .../predicate/DeclarationPredicate.kt | 113 ++++++++++++++++++ .../predicate/DeclarationPredicateVisitor.kt | 45 +++++++ 3 files changed, 162 insertions(+) create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/predicate/DeclarationPredicate.kt create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/predicate/DeclarationPredicateVisitor.kt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionsService.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionsService.kt index 3706691a1d1..a6da2953ae3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionsService.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionsService.kt @@ -98,6 +98,7 @@ class FirExtensionsService( require(annotation.classKind == ClassKind.ANNOTATION_CLASS) val fqName = annotation.symbol.classId.asSingleFqName() _annotations += fqName + userDefinedAnnotations.put(metaAnnotation, fqName) val extensions = extensionsWithMetaAnnotations[metaAnnotation] if (extensions.isEmpty()) return for (extension in extensions) { @@ -128,6 +129,9 @@ class FirExtensionsService( private val extensionsWithMetaAnnotations: Multimap = createMultimap() + // MetaAnnotation -> Annotations + val userDefinedAnnotations: Multimap = createMultimap() + var registeredExtensionsSize: Int = 0 private set diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/predicate/DeclarationPredicate.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/predicate/DeclarationPredicate.kt new file mode 100644 index 00000000000..43376c88bee --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/predicate/DeclarationPredicate.kt @@ -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 + abstract val metaAnnotations: Set + + internal abstract fun accept(visitor: DeclarationPredicateVisitor, data: D): R + + object Any : DeclarationPredicate() { + override val annotations: Set + get() = emptySet() + override val metaAnnotations: Set + get() = emptySet() + + override fun accept(visitor: DeclarationPredicateVisitor, data: D): R { + return visitor.visitAny(this, data) + } + } + + class Or(val a: DeclarationPredicate, val b: DeclarationPredicate) : DeclarationPredicate() { + override val annotations: Set = a.annotations + b.annotations + override val metaAnnotations: Set = a.metaAnnotations + b.metaAnnotations + + override fun accept(visitor: DeclarationPredicateVisitor, data: D): R { + return visitor.visitOr(this, data) + } + } + + class And(val a: DeclarationPredicate, val b: DeclarationPredicate) : DeclarationPredicate() { + override val annotations: Set = a.annotations + b.annotations + override val metaAnnotations: Set = a.metaAnnotations + b.metaAnnotations + + override fun accept(visitor: DeclarationPredicateVisitor, data: D): R { + return visitor.visitAnd(this, data) + } + } +} + +sealed class Annotated(final override val annotations: Set) : DeclarationPredicate() { + init { + require(annotations.isNotEmpty()) { + "Annotations should be not empty" + } + } + + final override val metaAnnotations: Set + get() = emptySet() + + override fun accept(visitor: DeclarationPredicateVisitor, data: D): R { + return visitor.visitAnnotated(this, data) + } +} + +class AnnotatedWith(annotations: Set) : Annotated(annotations) { + override fun accept(visitor: DeclarationPredicateVisitor, data: D): R { + return visitor.visitAnnotatedWith(this, data) + } +} + +class UnderAnnotatedWith(annotations: Set) : Annotated(annotations) { + override fun accept(visitor: DeclarationPredicateVisitor, data: D): R { + return visitor.visitUnderAnnotatedWith(this, data) + } +} + +sealed class MetaAnnotated(final override val metaAnnotations: Set) : DeclarationPredicate() { + init { + require(metaAnnotations.isNotEmpty()) { + "Annotations should be not empty" + } + } + + final override val annotations: Set + get() = emptySet() + + override fun accept(visitor: DeclarationPredicateVisitor, data: D): R { + return visitor.visitMetaAnnotated(this, data) + } +} + +class AnnotatedWithMeta(metaAnnotations: Set) : MetaAnnotated(metaAnnotations) { + override fun accept(visitor: DeclarationPredicateVisitor, data: D): R { + return visitor.visitAnnotatedWithMeta(this, data) + } +} + +class UnderMetaAnnotated(metaAnnotations: Set) : MetaAnnotated(metaAnnotations) { + override fun accept(visitor: DeclarationPredicateVisitor, 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) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/predicate/DeclarationPredicateVisitor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/predicate/DeclarationPredicateVisitor.kt new file mode 100644 index 00000000000..abc29fd6e6f --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/predicate/DeclarationPredicateVisitor.kt @@ -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 { + 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) + } +} \ No newline at end of file