diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index 57b22ea7723..d2b99680e51 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -185,7 +185,7 @@ public abstract class AnnotationCodegen { private void generateTargetAnnotation(@NotNull ClassDescriptor classDescriptor, @NotNull Set annotationDescriptorsAlreadyPresent) { String descriptor = Type.getType(Target.class).getDescriptor(); if (!annotationDescriptorsAlreadyPresent.add(descriptor)) return; - Set targets = AnnotationChecker.INSTANCE$.possibleTargetSet(classDescriptor); + Set targets = AnnotationChecker.Companion.possibleTargetSet(classDescriptor); Set javaTargets; if (targets == null) { javaTargets = getJavaTargetList(classDescriptor); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt index 0750e6b2a45..f38f932c1a9 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt @@ -82,7 +82,7 @@ public object JvmPlatformConfigurator : PlatformConfigurator( additionalSymbolUsageValidators = listOf(), - additionalAnnotationChecker = RepeatableAnnotationChecker + additionalAnnotationCheckers = listOf(RepeatableAnnotationChecker) ) { override fun configure(container: StorageComponentContainer) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt index e3b3ff15e18..a7c8c9fa1d7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt @@ -29,9 +29,7 @@ import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.* -public object AnnotationChecker { - - public var additionalChecker: AdditionalAnnotationChecker? = null +public class AnnotationChecker(private val additionalCheckers: Iterable) { public fun check(annotated: JetAnnotated, trace: BindingTrace, descriptor: ClassDescriptor? = null) { if (annotated is JetTypeParameter) return // TODO: support type parameter annotations @@ -71,25 +69,7 @@ public object AnnotationChecker { trace.report(Errors.REPEATED_ANNOTATION.on(entry)); } } - additionalChecker?.checkEntries(entries, actualTargets, trace) - } - - public fun possibleTargetSet(classDescriptor: ClassDescriptor): Set? { - val targetEntryDescriptor = classDescriptor.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.target) - ?: return null - val valueArguments = targetEntryDescriptor.allValueArguments - val valueArgument = valueArguments.entrySet().firstOrNull()?.getValue() as? ArrayValue ?: return null - return valueArgument.value.filterIsInstance().map { - KotlinTarget.valueOrNull(it.value.name.asString()) - }.filterNotNull().toSet() - } - - private fun possibleTargetSet(entry: JetAnnotationEntry, trace: BindingTrace): Set { - val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: return KotlinTarget.DEFAULT_TARGET_SET - // For descriptor with error type, all targets are considered as possible - if (descriptor.type.isError) return KotlinTarget.ALL_TARGET_SET - val classDescriptor = TypeUtils.getClassDescriptor(descriptor.type) ?: return KotlinTarget.DEFAULT_TARGET_SET - return possibleTargetSet(classDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET + additionalCheckers.forEach { it.checkEntries(entries, actualTargets, trace) } } private fun checkAnnotationEntry(entry: JetAnnotationEntry, actualTargets: List, trace: BindingTrace) { @@ -98,39 +78,60 @@ public object AnnotationChecker { trace.report(Errors.WRONG_ANNOTATION_TARGET.on(entry, actualTargets.firstOrNull()?.description ?: "unidentified target")) } - public fun getActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): List { - return when (annotated) { - is JetClassOrObject -> descriptor?.let { KotlinTarget.classActualTargets(it) } ?: listOf(CLASSIFIER) - is JetProperty -> - if (annotated.isLocal) { - listOf(LOCAL_VARIABLE) - } - else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody) { - listOf(MEMBER_PROPERTY, PROPERTY, FIELD) - } - else { - listOf(TOP_LEVEL_PROPERTY, PROPERTY, FIELD) - } - is JetParameter -> if (annotated.hasValOrVar()) listOf(PROPERTY_PARAMETER, MEMBER_PROPERTY, PROPERTY, FIELD) else listOf(VALUE_PARAMETER) - is JetConstructor<*> -> listOf(CONSTRUCTOR) - is JetFunction -> - if (annotated.isLocal) { - listOf(LOCAL_FUNCTION, FUNCTION) - } - else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody) { - listOf(MEMBER_FUNCTION, FUNCTION) - } - else { - listOf(TOP_LEVEL_FUNCTION, FUNCTION) - } - is JetPropertyAccessor -> if (annotated.isGetter) listOf(PROPERTY_GETTER) else listOf(PROPERTY_SETTER) - is JetPackageDirective -> listOf(PACKAGE) - is JetTypeReference -> listOf(TYPE) - is JetFile -> listOf(FILE) - is JetTypeParameter -> listOf(TYPE_PARAMETER) - is JetTypeProjection -> if (annotated.projectionKind == JetProjectionKind.STAR) listOf(STAR_PROJECTION) else listOf(TYPE_PROJECTION) - is JetClassInitializer -> listOf(INITIALIZER) - else -> listOf() + companion object { + + private fun possibleTargetSet(entry: JetAnnotationEntry, trace: BindingTrace): Set { + val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: return KotlinTarget.DEFAULT_TARGET_SET + // For descriptor with error type, all targets are considered as possible + if (descriptor.type.isError) return KotlinTarget.ALL_TARGET_SET + val classDescriptor = TypeUtils.getClassDescriptor(descriptor.type) ?: return KotlinTarget.DEFAULT_TARGET_SET + return possibleTargetSet(classDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET + } + + public fun possibleTargetSet(classDescriptor: ClassDescriptor): Set? { + val targetEntryDescriptor = classDescriptor.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.target) + ?: return null + val valueArguments = targetEntryDescriptor.allValueArguments + val valueArgument = valueArguments.entrySet().firstOrNull()?.getValue() as? ArrayValue ?: return null + return valueArgument.value.filterIsInstance().map { + KotlinTarget.valueOrNull(it.value.name.asString()) + }.filterNotNull().toSet() + } + + public fun getActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): List { + return when (annotated) { + is JetClassOrObject -> descriptor?.let { KotlinTarget.classActualTargets(it) } ?: listOf(CLASSIFIER) + is JetProperty -> + if (annotated.isLocal) { + listOf(LOCAL_VARIABLE) + } + else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody) { + listOf(MEMBER_PROPERTY, PROPERTY, FIELD) + } + else { + listOf(TOP_LEVEL_PROPERTY, PROPERTY, FIELD) + } + is JetParameter -> if (annotated.hasValOrVar()) listOf(PROPERTY_PARAMETER, MEMBER_PROPERTY, PROPERTY, FIELD) else listOf(VALUE_PARAMETER) + is JetConstructor<*> -> listOf(CONSTRUCTOR) + is JetFunction -> + if (annotated.isLocal) { + listOf(LOCAL_FUNCTION, FUNCTION) + } + else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody) { + listOf(MEMBER_FUNCTION, FUNCTION) + } + else { + listOf(TOP_LEVEL_FUNCTION, FUNCTION) + } + is JetPropertyAccessor -> if (annotated.isGetter) listOf(PROPERTY_GETTER) else listOf(PROPERTY_SETTER) + is JetPackageDirective -> listOf(PACKAGE) + is JetTypeReference -> listOf(TYPE) + is JetFile -> listOf(FILE) + is JetTypeParameter -> listOf(TYPE_PARAMETER) + is JetTypeProjection -> if (annotated.projectionKind == JetProjectionKind.STAR) listOf(STAR_PROJECTION) else listOf(TYPE_PROJECTION) + is JetClassInitializer -> listOf(INITIALIZER) + else -> listOf() + } } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java index ea1521b7b21..238e75e49cf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java @@ -54,7 +54,7 @@ import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE; public class BodyResolver { @NotNull private final ScriptBodyResolver scriptBodyResolverResolver; - @NotNull private final ModifiersChecker modifiersChecker; + @NotNull private final AnnotationChecker annotationChecker; @NotNull private final ExpressionTypingServices expressionTypingServices; @NotNull private final CallResolver callResolver; @NotNull private final ObservableBindingTrace trace; @@ -78,7 +78,7 @@ public class BodyResolver { @NotNull ScriptBodyResolver scriptBodyResolverResolver, @NotNull BindingTrace trace, @NotNull ValueParameterResolver valueParameterResolver, - @NotNull ModifiersChecker modifiersChecker + @NotNull AnnotationChecker annotationChecker ) { this.annotationResolver = annotationResolver; this.bodyResolveCache = bodyResolveCache; @@ -89,7 +89,7 @@ public class BodyResolver { this.expressionTypingServices = expressionTypingServices; this.functionAnalyzerExtension = functionAnalyzerExtension; this.scriptBodyResolverResolver = scriptBodyResolverResolver; - this.modifiersChecker = modifiersChecker; + this.annotationChecker = annotationChecker; this.trace = new ObservableBindingTrace(trace); this.valueParameterResolver = valueParameterResolver; } @@ -507,7 +507,7 @@ public class BodyResolver { } private void processModifiersOnInitializer(@NotNull JetModifierListOwner owner, @NotNull JetScope scope) { - AnnotationChecker.INSTANCE$.check(owner, trace, null); + annotationChecker.check(owner, trace, null); ModifierCheckerCore.INSTANCE$.check(owner, trace, null); JetModifierList modifierList = owner.getModifierList(); if (modifierList == null) return; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java index b2cd23de973..f2935f17087 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java @@ -47,21 +47,24 @@ public class DeclarationsChecker { @NotNull private final BindingTrace trace; @NotNull private final ModifiersChecker.ModifiersCheckingProcedure modifiersChecker; @NotNull private final DescriptorResolver descriptorResolver; + @NotNull private final AnnotationChecker annotationChecker; public DeclarationsChecker( @NotNull DescriptorResolver descriptorResolver, @NotNull ModifiersChecker modifiersChecker, + @NotNull AnnotationChecker annotationChecker, @NotNull BindingTrace trace ) { this.descriptorResolver = descriptorResolver; this.modifiersChecker = modifiersChecker.withTrace(trace); + this.annotationChecker = annotationChecker; this.trace = trace; } public void process(@NotNull BodiesResolveContext bodiesResolveContext) { for (JetFile file : bodiesResolveContext.getFiles()) { checkModifiersAndAnnotationsInPackageDirective(file); - AnnotationChecker.INSTANCE$.check(file, trace, null); + annotationChecker.check(file, trace, null); } Map classes = bodiesResolveContext.getDeclaredClasses(); @@ -133,7 +136,7 @@ public class DeclarationsChecker { } } } - AnnotationChecker.INSTANCE$.check(packageDirective, trace, null); + annotationChecker.check(packageDirective, trace, null); ModifierCheckerCore.INSTANCE$.check(packageDirective, trace, null); } @@ -279,7 +282,7 @@ public class DeclarationsChecker { if (typeParameter != null) { DescriptorResolver.checkConflictingUpperBounds(trace, typeParameter, jetTypeParameter); } - AnnotationChecker.INSTANCE$.check(jetTypeParameter, trace, null); + annotationChecker.check(jetTypeParameter, trace, null); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java index ce012509c28..64586da12c7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java @@ -192,7 +192,7 @@ public class ModifiersChecker { checkPlatformNameApplicability(descriptor); runDeclarationCheckers(modifierListOwner, descriptor); ClassDescriptor classDescriptor = descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null; - AnnotationChecker.INSTANCE$.check(modifierListOwner, trace, classDescriptor); + annotationChecker.check(modifierListOwner, trace, classDescriptor); } public void checkModifiersForLocalDeclaration( @@ -201,7 +201,7 @@ public class ModifiersChecker { ) { checkPlatformNameApplicability(descriptor); runDeclarationCheckers(modifierListOwner, descriptor); - AnnotationChecker.INSTANCE$.check(modifierListOwner, trace, + annotationChecker.check(modifierListOwner, trace, descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null); ModifierCheckerCore.INSTANCE$.check(modifierListOwner, trace, descriptor); } @@ -285,10 +285,14 @@ public class ModifiersChecker { } } + @NotNull + private final AnnotationChecker annotationChecker; + @NotNull private final Iterable declarationCheckers; - public ModifiersChecker(@NotNull Iterable declarationCheckers) { + public ModifiersChecker(@NotNull AnnotationChecker annotationChecker, @NotNull Iterable declarationCheckers) { + this.annotationChecker = annotationChecker; this.declarationCheckers = declarationCheckers; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt index 5f648f6604d..3470368a91b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt @@ -33,7 +33,7 @@ public abstract class TargetPlatform( public abstract val platformConfigurator: PlatformConfigurator public object Default : TargetPlatform("Default") { - override val platformConfigurator = PlatformConfigurator(DynamicTypesSettings(), listOf(), listOf(), listOf(), listOf()) + override val platformConfigurator = PlatformConfigurator(DynamicTypesSettings(), listOf(), listOf(), listOf(), listOf(), listOf()) } } @@ -49,7 +49,7 @@ public open class PlatformConfigurator( additionalCallCheckers: List, additionalTypeCheckers: List, additionalSymbolUsageValidators: List, - private val additionalAnnotationChecker: AdditionalAnnotationChecker? = null + private val additionalAnnotationCheckers: List ) { private val declarationCheckers: List = DEFAULT_DECLARATION_CHECKERS + additionalDeclarationCheckers @@ -64,7 +64,7 @@ public open class PlatformConfigurator( callCheckers.forEach { useInstance(it) } typeCheckers.forEach { useInstance(it) } useInstance(symbolUsageValidator) + additionalAnnotationCheckers.forEach { useInstance(it) } } - AnnotationChecker.additionalChecker = additionalAnnotationChecker } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java index 7948eabc67e..f389156dd7a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java @@ -49,14 +49,17 @@ public class ExpressionTypingServices { private final ExpressionTypingFacade expressionTypingFacade; private final ExpressionTypingComponents expressionTypingComponents; + @NotNull AnnotationChecker annotationChecker; @NotNull private final StatementFilter statementFilter; public ExpressionTypingServices( @NotNull ExpressionTypingComponents components, + @NotNull AnnotationChecker annotationChecker, @NotNull StatementFilter statementFilter, @NotNull ExpressionTypingVisitorDispatcher.ForDeclarations facade ) { this.expressionTypingComponents = components; + this.annotationChecker = annotationChecker; this.statementFilter = statementFilter; this.expressionTypingFacade = facade; } @@ -227,7 +230,8 @@ public class ExpressionTypingServices { return TypeInfoFactoryPackage.createTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context); } - ExpressionTypingInternals blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(expressionTypingComponents, scope); + ExpressionTypingInternals blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock( + expressionTypingComponents, annotationChecker, scope); ExpressionTypingContext newContext = context.replaceScope(scope).replaceExpectedType(NO_EXPECTED_TYPE); JetTypeInfo result = TypeInfoFactoryPackage.noTypeInfo(context); @@ -260,7 +264,7 @@ public class ExpressionTypingServices { newContext = newContext.replaceDataFlowInfo(newDataFlowInfo); // We take current data flow info if jump there is not possible } - blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(expressionTypingComponents, scope); + blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(expressionTypingComponents, annotationChecker, scope); } return result.replaceJumpOutPossible(jumpOutPossible).replaceJumpFlowInfo(beforeJumpInfo); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorDispatcher.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorDispatcher.java index 8fad90b3b74..43f6eadabef 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorDispatcher.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorDispatcher.java @@ -46,8 +46,8 @@ public abstract class ExpressionTypingVisitorDispatcher extends JetVisitor