001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.resolve;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.kotlin.descriptors.*;
022    import org.jetbrains.kotlin.descriptors.annotations.*;
023    import org.jetbrains.kotlin.diagnostics.Errors;
024    import org.jetbrains.kotlin.psi.*;
025    import org.jetbrains.kotlin.resolve.calls.CallResolver;
026    import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
027    import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
028    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
029    import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
030    import org.jetbrains.kotlin.resolve.constants.ConstantValue;
031    import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
032    import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
033    import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor;
034    import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationsContextImpl;
035    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
036    import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
037    import org.jetbrains.kotlin.storage.StorageManager;
038    import org.jetbrains.kotlin.types.ErrorUtils;
039    import org.jetbrains.kotlin.types.KotlinType;
040    
041    import javax.inject.Inject;
042    import java.util.ArrayList;
043    import java.util.List;
044    
045    import static org.jetbrains.kotlin.diagnostics.Errors.NOT_AN_ANNOTATION_CLASS;
046    import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
047    
048    public class AnnotationResolver {
049        @NotNull private final CallResolver callResolver;
050        @NotNull private final StorageManager storageManager;
051        @NotNull private TypeResolver typeResolver;
052        @NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
053    
054        public AnnotationResolver(
055                @NotNull CallResolver callResolver,
056                @NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
057                @NotNull StorageManager storageManager
058        ) {
059            this.callResolver = callResolver;
060            this.constantExpressionEvaluator = constantExpressionEvaluator;
061            this.storageManager = storageManager;
062        }
063    
064    
065        // component dependency cycle
066        @Inject
067        public void setTypeResolver(@NotNull TypeResolver typeResolver) {
068            this.typeResolver = typeResolver;
069        }
070    
071        @NotNull
072        public Annotations resolveAnnotationsWithoutArguments(
073                @NotNull LexicalScope scope,
074                @Nullable KtModifierList modifierList,
075                @NotNull BindingTrace trace
076        ) {
077            return resolveAnnotations(scope, modifierList, trace, false);
078        }
079    
080        @NotNull
081        public Annotations resolveAnnotationsWithArguments(
082                @NotNull LexicalScope scope,
083                @Nullable KtModifierList modifierList,
084                @NotNull BindingTrace trace
085        ) {
086            return resolveAnnotations(scope, modifierList, trace, true);
087        }
088    
089        @NotNull
090        public Annotations resolveAnnotationsWithoutArguments(
091                @NotNull LexicalScope scope,
092                @NotNull List<KtAnnotationEntry> annotationEntries,
093                @NotNull BindingTrace trace
094        ) {
095            return resolveAnnotationEntries(scope, annotationEntries, trace, false);
096        }
097    
098        @NotNull
099        public Annotations resolveAnnotationsWithArguments(
100                @NotNull LexicalScope scope,
101                @NotNull List<KtAnnotationEntry> annotationEntries,
102                @NotNull BindingTrace trace
103        ) {
104            return resolveAnnotationEntries(scope, annotationEntries, trace, true);
105        }
106    
107        private Annotations resolveAnnotations(
108                @NotNull LexicalScope scope,
109                @Nullable KtModifierList modifierList,
110                @NotNull BindingTrace trace,
111                boolean shouldResolveArguments
112        ) {
113            if (modifierList == null) {
114                return Annotations.Companion.getEMPTY();
115            }
116    
117            return resolveAnnotationEntries(scope, modifierList.getAnnotationEntries(), trace, shouldResolveArguments);
118        }
119    
120        private Annotations resolveAnnotationEntries(
121                @NotNull LexicalScope scope,
122                @NotNull List<KtAnnotationEntry> annotationEntryElements,
123                @NotNull BindingTrace trace,
124                boolean shouldResolveArguments
125        ) {
126            if (annotationEntryElements.isEmpty()) return Annotations.Companion.getEMPTY();
127            List<AnnotationWithTarget> result = new ArrayList<AnnotationWithTarget>(0);
128    
129            for (KtAnnotationEntry entryElement : annotationEntryElements) {
130                AnnotationDescriptor descriptor = trace.get(BindingContext.ANNOTATION, entryElement);
131                if (descriptor == null) {
132                    descriptor = new LazyAnnotationDescriptor(new LazyAnnotationsContextImpl(this, storageManager, trace, scope), entryElement);
133                }
134                if (shouldResolveArguments) {
135                    ForceResolveUtil.forceResolveAllContents(descriptor);
136                }
137    
138                KtAnnotationUseSiteTarget target = entryElement.getUseSiteTarget();
139                if (target != null) {
140                    result.add(new AnnotationWithTarget(descriptor, target.getAnnotationUseSiteTarget()));
141                }
142                else {
143                    result.add(new AnnotationWithTarget(descriptor, null));
144                }
145            }
146            return AnnotationsImpl.create(result);
147        }
148    
149        @NotNull
150        public KotlinType resolveAnnotationType(@NotNull LexicalScope scope, @NotNull KtAnnotationEntry entryElement, @NotNull BindingTrace trace) {
151            KtTypeReference typeReference = entryElement.getTypeReference();
152            if (typeReference == null) {
153                return ErrorUtils.createErrorType("No type reference: " + entryElement.getText());
154            }
155    
156            KotlinType type = typeResolver.resolveType(scope, typeReference, trace, true);
157            if (!(type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) {
158                return ErrorUtils.createErrorType("Not an annotation: " + type);
159            }
160            return type;
161        }
162    
163        public static void checkAnnotationType(
164                @NotNull KtAnnotationEntry entryElement,
165                @NotNull BindingTrace trace,
166                @NotNull OverloadResolutionResults<FunctionDescriptor> results
167        ) {
168            if (!results.isSingleResult()) return;
169            FunctionDescriptor descriptor = results.getResultingDescriptor();
170            if (!ErrorUtils.isError(descriptor)) {
171                if (descriptor instanceof ConstructorDescriptor) {
172                    ConstructorDescriptor constructor = (ConstructorDescriptor)descriptor;
173                    ClassDescriptor classDescriptor = constructor.getContainingDeclaration();
174                    if (classDescriptor.getKind() != ClassKind.ANNOTATION_CLASS) {
175                        trace.report(NOT_AN_ANNOTATION_CLASS.on(entryElement, classDescriptor));
176                    }
177                }
178                else {
179                    trace.report(NOT_AN_ANNOTATION_CLASS.on(entryElement, descriptor));
180                }
181            }
182        }
183    
184        @NotNull
185        public OverloadResolutionResults<FunctionDescriptor> resolveAnnotationCall(
186                KtAnnotationEntry annotationEntry,
187                LexicalScope scope,
188                BindingTrace trace
189        ) {
190            return callResolver.resolveFunctionCall(
191                    trace, scope,
192                    CallMaker.makeCall(null, null, annotationEntry),
193                    NO_EXPECTED_TYPE,
194                    DataFlowInfo.EMPTY,
195                    true
196            );
197        }
198    
199        public static void reportUnsupportedAnnotationForTypeParameter(@NotNull KtTypeParameter jetTypeParameter, @NotNull BindingTrace trace) {
200            KtModifierList modifierList = jetTypeParameter.getModifierList();
201            if (modifierList == null) return;
202    
203            for (KtAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) {
204                trace.report(Errors.UNSUPPORTED.on(annotationEntry, "Annotations for type parameters are not supported yet"));
205            }
206        }
207    
208        @Nullable
209        public ConstantValue<?> getAnnotationArgumentValue(
210                @NotNull BindingTrace trace,
211                @NotNull ValueParameterDescriptor valueParameter,
212                @NotNull ResolvedValueArgument resolvedArgument
213        ) {
214            return constantExpressionEvaluator.getAnnotationArgumentValue(trace, valueParameter, resolvedArgument);
215        }
216    }