/* * Copyright 2010-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jetbrains.kotlin.resolve; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.*; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.calls.CallResolver; import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory; import org.jetbrains.kotlin.resolve.calls.util.CallMaker; import org.jetbrains.kotlin.resolve.constants.ConstantValue; import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil; import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor; import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationsContextImpl; import org.jetbrains.kotlin.resolve.scopes.LexicalScope; import org.jetbrains.kotlin.storage.StorageManager; import org.jetbrains.kotlin.types.ErrorUtils; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.TypeUtils; import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext; import javax.inject.Inject; import java.util.ArrayList; import java.util.List; import static org.jetbrains.kotlin.diagnostics.Errors.NOT_AN_ANNOTATION_CLASS; import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE; public class AnnotationResolverImpl extends AnnotationResolver { @NotNull private final CallResolver callResolver; @NotNull private final StorageManager storageManager; @NotNull private TypeResolver typeResolver; @NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator; public AnnotationResolverImpl( @NotNull CallResolver callResolver, @NotNull ConstantExpressionEvaluator constantExpressionEvaluator, @NotNull StorageManager storageManager ) { this.callResolver = callResolver; this.constantExpressionEvaluator = constantExpressionEvaluator; this.storageManager = storageManager; } // component dependency cycle @Inject public void setTypeResolver(@NotNull TypeResolver typeResolver) { this.typeResolver = typeResolver; } @NotNull @Override public Annotations resolveAnnotationEntries( @NotNull LexicalScope scope, @NotNull List<KtAnnotationEntry> annotationEntryElements, @NotNull BindingTrace trace, boolean shouldResolveArguments ) { if (annotationEntryElements.isEmpty()) return Annotations.Companion.getEMPTY(); List<AnnotationWithTarget> result = new ArrayList<>(0); for (KtAnnotationEntry entryElement : annotationEntryElements) { AnnotationDescriptor descriptor = trace.get(BindingContext.ANNOTATION, entryElement); if (descriptor == null) { descriptor = new LazyAnnotationDescriptor(new LazyAnnotationsContextImpl(this, storageManager, trace, scope), entryElement); } if (shouldResolveArguments) { ForceResolveUtil.forceResolveAllContents(descriptor); } KtAnnotationUseSiteTarget target = entryElement.getUseSiteTarget(); if (target != null) { result.add(new AnnotationWithTarget(descriptor, target.getAnnotationUseSiteTarget())); } else { result.add(new AnnotationWithTarget(descriptor, null)); } } return AnnotationsImpl.create(result); } @Override @NotNull public KotlinType resolveAnnotationType( @NotNull LexicalScope scope, @NotNull KtAnnotationEntry entryElement, @NotNull BindingTrace trace ) { KtTypeReference typeReference = entryElement.getTypeReference(); if (typeReference == null) { return ErrorUtils.createErrorType("No type reference: " + entryElement.getText()); } KotlinType type = typeResolver.resolveType(scope, typeReference, trace, true); if (!(type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) { return ErrorUtils.createErrorType("Not an annotation: " + type); } return type; } public static void checkAnnotationType( @NotNull KtAnnotationEntry entryElement, @NotNull BindingTrace trace, @NotNull OverloadResolutionResults<FunctionDescriptor> results ) { if (!results.isSingleResult()) return; FunctionDescriptor descriptor = results.getResultingDescriptor(); if (!ErrorUtils.isError(descriptor)) { if (descriptor instanceof ConstructorDescriptor) { ConstructorDescriptor constructor = (ConstructorDescriptor)descriptor; ClassDescriptor classDescriptor = constructor.getConstructedClass(); if (classDescriptor.getKind() != ClassKind.ANNOTATION_CLASS) { trace.report(NOT_AN_ANNOTATION_CLASS.on(entryElement, classDescriptor)); } } else { trace.report(NOT_AN_ANNOTATION_CLASS.on(entryElement, descriptor)); } } } @Override @NotNull public OverloadResolutionResults<FunctionDescriptor> resolveAnnotationCall( @NotNull KtAnnotationEntry annotationEntry, @NotNull LexicalScope scope, @NotNull BindingTrace trace ) { return callResolver.resolveFunctionCall( trace, scope, CallMaker.makeCall(null, null, annotationEntry), NO_EXPECTED_TYPE, DataFlowInfoFactory.EMPTY, true ); } public static void reportUnsupportedAnnotationForTypeParameter(@NotNull KtTypeParameter jetTypeParameter, @NotNull BindingTrace trace) { KtModifierList modifierList = jetTypeParameter.getModifierList(); if (modifierList == null) return; for (KtAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) { trace.report(Errors.UNSUPPORTED.on(annotationEntry, "Annotations for type parameters are not supported yet")); } } @Override @Nullable public ConstantValue<?> getAnnotationArgumentValue( @NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter, @NotNull ResolvedValueArgument resolvedArgument ) { return constantExpressionEvaluator.getAnnotationArgumentValue(trace, valueParameter, resolvedArgument); } }