Refactoring of repeatable on retention SOURCE check (correct additional checker usage)

This commit is contained in:
Mikhail Glukhikh
2015-08-03 18:34:08 +03:00
parent 992c019c1e
commit 61fbe0d1e8
10 changed files with 95 additions and 78 deletions
@@ -185,7 +185,7 @@ public abstract class AnnotationCodegen {
private void generateTargetAnnotation(@NotNull ClassDescriptor classDescriptor, @NotNull Set<String> annotationDescriptorsAlreadyPresent) { private void generateTargetAnnotation(@NotNull ClassDescriptor classDescriptor, @NotNull Set<String> annotationDescriptorsAlreadyPresent) {
String descriptor = Type.getType(Target.class).getDescriptor(); String descriptor = Type.getType(Target.class).getDescriptor();
if (!annotationDescriptorsAlreadyPresent.add(descriptor)) return; if (!annotationDescriptorsAlreadyPresent.add(descriptor)) return;
Set<KotlinTarget> targets = AnnotationChecker.INSTANCE$.possibleTargetSet(classDescriptor); Set<KotlinTarget> targets = AnnotationChecker.Companion.possibleTargetSet(classDescriptor);
Set<ElementType> javaTargets; Set<ElementType> javaTargets;
if (targets == null) { if (targets == null) {
javaTargets = getJavaTargetList(classDescriptor); javaTargets = getJavaTargetList(classDescriptor);
@@ -82,7 +82,7 @@ public object JvmPlatformConfigurator : PlatformConfigurator(
additionalSymbolUsageValidators = listOf(), additionalSymbolUsageValidators = listOf(),
additionalAnnotationChecker = RepeatableAnnotationChecker additionalAnnotationCheckers = listOf(RepeatableAnnotationChecker)
) { ) {
override fun configure(container: StorageComponentContainer) { override fun configure(container: StorageComponentContainer) {
@@ -29,9 +29,7 @@ import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.* import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.*
public object AnnotationChecker { public class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnotationChecker>) {
public var additionalChecker: AdditionalAnnotationChecker? = null
public fun check(annotated: JetAnnotated, trace: BindingTrace, descriptor: ClassDescriptor? = null) { public fun check(annotated: JetAnnotated, trace: BindingTrace, descriptor: ClassDescriptor? = null) {
if (annotated is JetTypeParameter) return // TODO: support type parameter annotations if (annotated is JetTypeParameter) return // TODO: support type parameter annotations
@@ -71,7 +69,23 @@ public object AnnotationChecker {
trace.report(Errors.REPEATED_ANNOTATION.on(entry)); trace.report(Errors.REPEATED_ANNOTATION.on(entry));
} }
} }
additionalChecker?.checkEntries(entries, actualTargets, trace) additionalCheckers.forEach { it.checkEntries(entries, actualTargets, trace) }
}
private fun checkAnnotationEntry(entry: JetAnnotationEntry, actualTargets: List<KotlinTarget>, trace: BindingTrace) {
val possibleTargets = possibleTargetSet(entry, trace)
if (actualTargets.any { it in possibleTargets }) return
trace.report(Errors.WRONG_ANNOTATION_TARGET.on(entry, actualTargets.firstOrNull()?.description ?: "unidentified target"))
}
companion object {
private fun possibleTargetSet(entry: JetAnnotationEntry, trace: BindingTrace): Set<KotlinTarget> {
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<KotlinTarget>? { public fun possibleTargetSet(classDescriptor: ClassDescriptor): Set<KotlinTarget>? {
@@ -84,20 +98,6 @@ public object AnnotationChecker {
}.filterNotNull().toSet() }.filterNotNull().toSet()
} }
private fun possibleTargetSet(entry: JetAnnotationEntry, trace: BindingTrace): Set<KotlinTarget> {
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
}
private fun checkAnnotationEntry(entry: JetAnnotationEntry, actualTargets: List<KotlinTarget>, trace: BindingTrace) {
val possibleTargets = possibleTargetSet(entry, trace)
if (actualTargets.any { it in possibleTargets }) return
trace.report(Errors.WRONG_ANNOTATION_TARGET.on(entry, actualTargets.firstOrNull()?.description ?: "unidentified target"))
}
public fun getActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): List<KotlinTarget> { public fun getActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): List<KotlinTarget> {
return when (annotated) { return when (annotated) {
is JetClassOrObject -> descriptor?.let { KotlinTarget.classActualTargets(it) } ?: listOf(CLASSIFIER) is JetClassOrObject -> descriptor?.let { KotlinTarget.classActualTargets(it) } ?: listOf(CLASSIFIER)
@@ -133,6 +133,7 @@ public object AnnotationChecker {
else -> listOf() else -> listOf()
} }
} }
}
} }
public interface AdditionalAnnotationChecker { public interface AdditionalAnnotationChecker {
@@ -54,7 +54,7 @@ import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
public class BodyResolver { public class BodyResolver {
@NotNull private final ScriptBodyResolver scriptBodyResolverResolver; @NotNull private final ScriptBodyResolver scriptBodyResolverResolver;
@NotNull private final ModifiersChecker modifiersChecker; @NotNull private final AnnotationChecker annotationChecker;
@NotNull private final ExpressionTypingServices expressionTypingServices; @NotNull private final ExpressionTypingServices expressionTypingServices;
@NotNull private final CallResolver callResolver; @NotNull private final CallResolver callResolver;
@NotNull private final ObservableBindingTrace trace; @NotNull private final ObservableBindingTrace trace;
@@ -78,7 +78,7 @@ public class BodyResolver {
@NotNull ScriptBodyResolver scriptBodyResolverResolver, @NotNull ScriptBodyResolver scriptBodyResolverResolver,
@NotNull BindingTrace trace, @NotNull BindingTrace trace,
@NotNull ValueParameterResolver valueParameterResolver, @NotNull ValueParameterResolver valueParameterResolver,
@NotNull ModifiersChecker modifiersChecker @NotNull AnnotationChecker annotationChecker
) { ) {
this.annotationResolver = annotationResolver; this.annotationResolver = annotationResolver;
this.bodyResolveCache = bodyResolveCache; this.bodyResolveCache = bodyResolveCache;
@@ -89,7 +89,7 @@ public class BodyResolver {
this.expressionTypingServices = expressionTypingServices; this.expressionTypingServices = expressionTypingServices;
this.functionAnalyzerExtension = functionAnalyzerExtension; this.functionAnalyzerExtension = functionAnalyzerExtension;
this.scriptBodyResolverResolver = scriptBodyResolverResolver; this.scriptBodyResolverResolver = scriptBodyResolverResolver;
this.modifiersChecker = modifiersChecker; this.annotationChecker = annotationChecker;
this.trace = new ObservableBindingTrace(trace); this.trace = new ObservableBindingTrace(trace);
this.valueParameterResolver = valueParameterResolver; this.valueParameterResolver = valueParameterResolver;
} }
@@ -507,7 +507,7 @@ public class BodyResolver {
} }
private void processModifiersOnInitializer(@NotNull JetModifierListOwner owner, @NotNull JetScope scope) { 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); ModifierCheckerCore.INSTANCE$.check(owner, trace, null);
JetModifierList modifierList = owner.getModifierList(); JetModifierList modifierList = owner.getModifierList();
if (modifierList == null) return; if (modifierList == null) return;
@@ -47,21 +47,24 @@ public class DeclarationsChecker {
@NotNull private final BindingTrace trace; @NotNull private final BindingTrace trace;
@NotNull private final ModifiersChecker.ModifiersCheckingProcedure modifiersChecker; @NotNull private final ModifiersChecker.ModifiersCheckingProcedure modifiersChecker;
@NotNull private final DescriptorResolver descriptorResolver; @NotNull private final DescriptorResolver descriptorResolver;
@NotNull private final AnnotationChecker annotationChecker;
public DeclarationsChecker( public DeclarationsChecker(
@NotNull DescriptorResolver descriptorResolver, @NotNull DescriptorResolver descriptorResolver,
@NotNull ModifiersChecker modifiersChecker, @NotNull ModifiersChecker modifiersChecker,
@NotNull AnnotationChecker annotationChecker,
@NotNull BindingTrace trace @NotNull BindingTrace trace
) { ) {
this.descriptorResolver = descriptorResolver; this.descriptorResolver = descriptorResolver;
this.modifiersChecker = modifiersChecker.withTrace(trace); this.modifiersChecker = modifiersChecker.withTrace(trace);
this.annotationChecker = annotationChecker;
this.trace = trace; this.trace = trace;
} }
public void process(@NotNull BodiesResolveContext bodiesResolveContext) { public void process(@NotNull BodiesResolveContext bodiesResolveContext) {
for (JetFile file : bodiesResolveContext.getFiles()) { for (JetFile file : bodiesResolveContext.getFiles()) {
checkModifiersAndAnnotationsInPackageDirective(file); checkModifiersAndAnnotationsInPackageDirective(file);
AnnotationChecker.INSTANCE$.check(file, trace, null); annotationChecker.check(file, trace, null);
} }
Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> classes = bodiesResolveContext.getDeclaredClasses(); Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> 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); ModifierCheckerCore.INSTANCE$.check(packageDirective, trace, null);
} }
@@ -279,7 +282,7 @@ public class DeclarationsChecker {
if (typeParameter != null) { if (typeParameter != null) {
DescriptorResolver.checkConflictingUpperBounds(trace, typeParameter, jetTypeParameter); DescriptorResolver.checkConflictingUpperBounds(trace, typeParameter, jetTypeParameter);
} }
AnnotationChecker.INSTANCE$.check(jetTypeParameter, trace, null); annotationChecker.check(jetTypeParameter, trace, null);
} }
} }
@@ -192,7 +192,7 @@ public class ModifiersChecker {
checkPlatformNameApplicability(descriptor); checkPlatformNameApplicability(descriptor);
runDeclarationCheckers(modifierListOwner, descriptor); runDeclarationCheckers(modifierListOwner, descriptor);
ClassDescriptor classDescriptor = descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null; ClassDescriptor classDescriptor = descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null;
AnnotationChecker.INSTANCE$.check(modifierListOwner, trace, classDescriptor); annotationChecker.check(modifierListOwner, trace, classDescriptor);
} }
public void checkModifiersForLocalDeclaration( public void checkModifiersForLocalDeclaration(
@@ -201,7 +201,7 @@ public class ModifiersChecker {
) { ) {
checkPlatformNameApplicability(descriptor); checkPlatformNameApplicability(descriptor);
runDeclarationCheckers(modifierListOwner, descriptor); runDeclarationCheckers(modifierListOwner, descriptor);
AnnotationChecker.INSTANCE$.check(modifierListOwner, trace, annotationChecker.check(modifierListOwner, trace,
descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null); descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null);
ModifierCheckerCore.INSTANCE$.check(modifierListOwner, trace, descriptor); ModifierCheckerCore.INSTANCE$.check(modifierListOwner, trace, descriptor);
} }
@@ -285,10 +285,14 @@ public class ModifiersChecker {
} }
} }
@NotNull
private final AnnotationChecker annotationChecker;
@NotNull @NotNull
private final Iterable<DeclarationChecker> declarationCheckers; private final Iterable<DeclarationChecker> declarationCheckers;
public ModifiersChecker(@NotNull Iterable<DeclarationChecker> declarationCheckers) { public ModifiersChecker(@NotNull AnnotationChecker annotationChecker, @NotNull Iterable<DeclarationChecker> declarationCheckers) {
this.annotationChecker = annotationChecker;
this.declarationCheckers = declarationCheckers; this.declarationCheckers = declarationCheckers;
} }
@@ -33,7 +33,7 @@ public abstract class TargetPlatform(
public abstract val platformConfigurator: PlatformConfigurator public abstract val platformConfigurator: PlatformConfigurator
public object Default : TargetPlatform("Default") { 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<CallChecker>, additionalCallCheckers: List<CallChecker>,
additionalTypeCheckers: List<AdditionalTypeChecker>, additionalTypeCheckers: List<AdditionalTypeChecker>,
additionalSymbolUsageValidators: List<SymbolUsageValidator>, additionalSymbolUsageValidators: List<SymbolUsageValidator>,
private val additionalAnnotationChecker: AdditionalAnnotationChecker? = null private val additionalAnnotationCheckers: List<AdditionalAnnotationChecker>
) { ) {
private val declarationCheckers: List<DeclarationChecker> = DEFAULT_DECLARATION_CHECKERS + additionalDeclarationCheckers private val declarationCheckers: List<DeclarationChecker> = DEFAULT_DECLARATION_CHECKERS + additionalDeclarationCheckers
@@ -64,7 +64,7 @@ public open class PlatformConfigurator(
callCheckers.forEach { useInstance(it) } callCheckers.forEach { useInstance(it) }
typeCheckers.forEach { useInstance(it) } typeCheckers.forEach { useInstance(it) }
useInstance(symbolUsageValidator) useInstance(symbolUsageValidator)
additionalAnnotationCheckers.forEach { useInstance(it) }
} }
AnnotationChecker.additionalChecker = additionalAnnotationChecker
} }
} }
@@ -49,14 +49,17 @@ public class ExpressionTypingServices {
private final ExpressionTypingFacade expressionTypingFacade; private final ExpressionTypingFacade expressionTypingFacade;
private final ExpressionTypingComponents expressionTypingComponents; private final ExpressionTypingComponents expressionTypingComponents;
@NotNull AnnotationChecker annotationChecker;
@NotNull private final StatementFilter statementFilter; @NotNull private final StatementFilter statementFilter;
public ExpressionTypingServices( public ExpressionTypingServices(
@NotNull ExpressionTypingComponents components, @NotNull ExpressionTypingComponents components,
@NotNull AnnotationChecker annotationChecker,
@NotNull StatementFilter statementFilter, @NotNull StatementFilter statementFilter,
@NotNull ExpressionTypingVisitorDispatcher.ForDeclarations facade @NotNull ExpressionTypingVisitorDispatcher.ForDeclarations facade
) { ) {
this.expressionTypingComponents = components; this.expressionTypingComponents = components;
this.annotationChecker = annotationChecker;
this.statementFilter = statementFilter; this.statementFilter = statementFilter;
this.expressionTypingFacade = facade; this.expressionTypingFacade = facade;
} }
@@ -227,7 +230,8 @@ public class ExpressionTypingServices {
return TypeInfoFactoryPackage.createTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context); 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); ExpressionTypingContext newContext = context.replaceScope(scope).replaceExpectedType(NO_EXPECTED_TYPE);
JetTypeInfo result = TypeInfoFactoryPackage.noTypeInfo(context); JetTypeInfo result = TypeInfoFactoryPackage.noTypeInfo(context);
@@ -260,7 +264,7 @@ public class ExpressionTypingServices {
newContext = newContext.replaceDataFlowInfo(newDataFlowInfo); newContext = newContext.replaceDataFlowInfo(newDataFlowInfo);
// We take current data flow info if jump there is not possible // 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); return result.replaceJumpOutPossible(jumpOutPossible).replaceJumpFlowInfo(beforeJumpInfo);
} }
@@ -46,8 +46,8 @@ public abstract class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTy
private static final Logger LOG = Logger.getInstance(ExpressionTypingVisitor.class); private static final Logger LOG = Logger.getInstance(ExpressionTypingVisitor.class);
public static class ForDeclarations extends ExpressionTypingVisitorDispatcher { public static class ForDeclarations extends ExpressionTypingVisitorDispatcher {
public ForDeclarations(@NotNull ExpressionTypingComponents components) { public ForDeclarations(@NotNull ExpressionTypingComponents components, @NotNull AnnotationChecker annotationChecker) {
super(components); super(components, annotationChecker);
} }
@Override @Override
@@ -64,9 +64,10 @@ public abstract class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTy
public ForBlock( public ForBlock(
@NotNull ExpressionTypingComponents components, @NotNull ExpressionTypingComponents components,
@NotNull AnnotationChecker annotationChecker,
@NotNull WritableScope writableScope @NotNull WritableScope writableScope
) { ) {
super(components); super(components, annotationChecker);
this.visitorForBlock = new ExpressionTypingVisitorForStatements( this.visitorForBlock = new ExpressionTypingVisitorForStatements(
this, writableScope, basic, controlStructures, patterns, functions this, writableScope, basic, controlStructures, patterns, functions
); );
@@ -79,15 +80,18 @@ public abstract class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTy
} }
private final ExpressionTypingComponents components; private final ExpressionTypingComponents components;
@NotNull private final AnnotationChecker annotationChecker;
protected final BasicExpressionTypingVisitor basic; protected final BasicExpressionTypingVisitor basic;
protected final FunctionsTypingVisitor functions; protected final FunctionsTypingVisitor functions;
protected final ControlStructureTypingVisitor controlStructures; protected final ControlStructureTypingVisitor controlStructures;
protected final PatternMatchingTypingVisitor patterns; protected final PatternMatchingTypingVisitor patterns;
private ExpressionTypingVisitorDispatcher( private ExpressionTypingVisitorDispatcher(
@NotNull ExpressionTypingComponents components @NotNull ExpressionTypingComponents components,
@NotNull AnnotationChecker annotationChecker
) { ) {
this.components = components; this.components = components;
this.annotationChecker = annotationChecker;
this.basic = new BasicExpressionTypingVisitor(this); this.basic = new BasicExpressionTypingVisitor(this);
this.controlStructures = new ControlStructureTypingVisitor(this); this.controlStructures = new ControlStructureTypingVisitor(this);
this.patterns = new PatternMatchingTypingVisitor(this); this.patterns = new PatternMatchingTypingVisitor(this);
@@ -128,7 +132,7 @@ public abstract class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTy
@NotNull @NotNull
public final JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context) { public final JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context) {
JetTypeInfo result = getTypeInfo(expression, context, this); JetTypeInfo result = getTypeInfo(expression, context, this);
AnnotationChecker.INSTANCE$.checkExpression(expression, context.trace); annotationChecker.checkExpression(expression, context.trace);
return result; return result;
} }
@@ -27,7 +27,8 @@ public object JsPlatformConfigurator : PlatformConfigurator(
additionalDeclarationCheckers = listOf(NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker(), ClassDeclarationChecker()), additionalDeclarationCheckers = listOf(NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker(), ClassDeclarationChecker()),
additionalCallCheckers = listOf(), additionalCallCheckers = listOf(),
additionalTypeCheckers = listOf(), additionalTypeCheckers = listOf(),
additionalSymbolUsageValidators = listOf() additionalSymbolUsageValidators = listOf(),
additionalAnnotationCheckers = listOf()
) { ) {
override fun configure(container: StorageComponentContainer) { override fun configure(container: StorageComponentContainer) {
super.configure(container) super.configure(container)