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.DataFlowInfoFactory;
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.storage.StorageManager;
037    import org.jetbrains.kotlin.types.ErrorUtils;
038    import org.jetbrains.kotlin.types.KotlinType;
039    
040    import javax.inject.Inject;
041    import java.util.ArrayList;
042    import java.util.List;
043    
044    import static org.jetbrains.kotlin.diagnostics.Errors.NOT_AN_ANNOTATION_CLASS;
045    import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
046    
047    public class AnnotationResolver {
048        @NotNull private final CallResolver callResolver;
049        @NotNull private final StorageManager storageManager;
050        @NotNull private TypeResolver typeResolver;
051        @NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
052    
053        public AnnotationResolver(
054                @NotNull CallResolver callResolver,
055                @NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
056                @NotNull StorageManager storageManager
057        ) {
058            this.callResolver = callResolver;
059            this.constantExpressionEvaluator = constantExpressionEvaluator;
060            this.storageManager = storageManager;
061        }
062    
063    
064        // component dependency cycle
065        @Inject
066        public void setTypeResolver(@NotNull TypeResolver typeResolver) {
067            this.typeResolver = typeResolver;
068        }
069    
070        @NotNull
071        public Annotations resolveAnnotationsWithoutArguments(
072                @NotNull LexicalScope scope,
073                @Nullable KtModifierList modifierList,
074                @NotNull BindingTrace trace
075        ) {
076            return resolveAnnotations(scope, modifierList, trace, false);
077        }
078    
079        @NotNull
080        public Annotations resolveAnnotationsWithArguments(
081                @NotNull LexicalScope scope,
082                @Nullable KtModifierList modifierList,
083                @NotNull BindingTrace trace
084        ) {
085            return resolveAnnotations(scope, modifierList, trace, true);
086        }
087    
088        @NotNull
089        public Annotations resolveAnnotationsWithoutArguments(
090                @NotNull LexicalScope scope,
091                @NotNull List<KtAnnotationEntry> annotationEntries,
092                @NotNull BindingTrace trace
093        ) {
094            return resolveAnnotationEntries(scope, annotationEntries, trace, false);
095        }
096    
097        @NotNull
098        public Annotations resolveAnnotationsWithArguments(
099                @NotNull LexicalScope scope,
100                @NotNull List<KtAnnotationEntry> annotationEntries,
101                @NotNull BindingTrace trace
102        ) {
103            return resolveAnnotationEntries(scope, annotationEntries, trace, true);
104        }
105    
106        private Annotations resolveAnnotations(
107                @NotNull LexicalScope scope,
108                @Nullable KtModifierList modifierList,
109                @NotNull BindingTrace trace,
110                boolean shouldResolveArguments
111        ) {
112            if (modifierList == null) {
113                return Annotations.Companion.getEMPTY();
114            }
115    
116            return resolveAnnotationEntries(scope, modifierList.getAnnotationEntries(), trace, shouldResolveArguments);
117        }
118    
119        private Annotations resolveAnnotationEntries(
120                @NotNull LexicalScope scope,
121                @NotNull List<KtAnnotationEntry> annotationEntryElements,
122                @NotNull BindingTrace trace,
123                boolean shouldResolveArguments
124        ) {
125            if (annotationEntryElements.isEmpty()) return Annotations.Companion.getEMPTY();
126            List<AnnotationWithTarget> result = new ArrayList<AnnotationWithTarget>(0);
127    
128            for (KtAnnotationEntry entryElement : annotationEntryElements) {
129                AnnotationDescriptor descriptor = trace.get(BindingContext.ANNOTATION, entryElement);
130                if (descriptor == null) {
131                    descriptor = new LazyAnnotationDescriptor(new LazyAnnotationsContextImpl(this, storageManager, trace, scope), entryElement);
132                }
133                if (shouldResolveArguments) {
134                    ForceResolveUtil.forceResolveAllContents(descriptor);
135                }
136    
137                KtAnnotationUseSiteTarget target = entryElement.getUseSiteTarget();
138                if (target != null) {
139                    result.add(new AnnotationWithTarget(descriptor, target.getAnnotationUseSiteTarget()));
140                }
141                else {
142                    result.add(new AnnotationWithTarget(descriptor, null));
143                }
144            }
145            return AnnotationsImpl.create(result);
146        }
147    
148        @NotNull
149        public KotlinType resolveAnnotationType(@NotNull LexicalScope scope, @NotNull KtAnnotationEntry entryElement, @NotNull BindingTrace trace) {
150            KtTypeReference typeReference = entryElement.getTypeReference();
151            if (typeReference == null) {
152                return ErrorUtils.createErrorType("No type reference: " + entryElement.getText());
153            }
154    
155            KotlinType type = typeResolver.resolveType(scope, typeReference, trace, true);
156            if (!(type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) {
157                return ErrorUtils.createErrorType("Not an annotation: " + type);
158            }
159            return type;
160        }
161    
162        public static void checkAnnotationType(
163                @NotNull KtAnnotationEntry entryElement,
164                @NotNull BindingTrace trace,
165                @NotNull OverloadResolutionResults<FunctionDescriptor> results
166        ) {
167            if (!results.isSingleResult()) return;
168            FunctionDescriptor descriptor = results.getResultingDescriptor();
169            if (!ErrorUtils.isError(descriptor)) {
170                if (descriptor instanceof ConstructorDescriptor) {
171                    ConstructorDescriptor constructor = (ConstructorDescriptor)descriptor;
172                    ClassDescriptor classDescriptor = constructor.getContainingDeclaration();
173                    if (classDescriptor.getKind() != ClassKind.ANNOTATION_CLASS) {
174                        trace.report(NOT_AN_ANNOTATION_CLASS.on(entryElement, classDescriptor));
175                    }
176                }
177                else {
178                    trace.report(NOT_AN_ANNOTATION_CLASS.on(entryElement, descriptor));
179                }
180            }
181        }
182    
183        @NotNull
184        public OverloadResolutionResults<FunctionDescriptor> resolveAnnotationCall(
185                KtAnnotationEntry annotationEntry,
186                LexicalScope scope,
187                BindingTrace trace
188        ) {
189            return callResolver.resolveFunctionCall(
190                    trace, scope,
191                    CallMaker.makeCall(null, null, annotationEntry),
192                    NO_EXPECTED_TYPE,
193                    DataFlowInfoFactory.EMPTY,
194                    true
195            );
196        }
197    
198        public static void reportUnsupportedAnnotationForTypeParameter(@NotNull KtTypeParameter jetTypeParameter, @NotNull BindingTrace trace) {
199            KtModifierList modifierList = jetTypeParameter.getModifierList();
200            if (modifierList == null) return;
201    
202            for (KtAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) {
203                trace.report(Errors.UNSUPPORTED.on(annotationEntry, "Annotations for type parameters are not supported yet"));
204            }
205        }
206    
207        @Nullable
208        public ConstantValue<?> getAnnotationArgumentValue(
209                @NotNull BindingTrace trace,
210                @NotNull ValueParameterDescriptor valueParameter,
211                @NotNull ResolvedValueArgument resolvedArgument
212        ) {
213            return constantExpressionEvaluator.getAnnotationArgumentValue(trace, valueParameter, resolvedArgument);
214        }
215    }