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.builtins.KotlinBuiltIns;
022    import org.jetbrains.kotlin.descriptors.*;
023    import org.jetbrains.kotlin.descriptors.annotations.*;
024    import org.jetbrains.kotlin.diagnostics.Errors;
025    import org.jetbrains.kotlin.lexer.JetModifierKeywordToken;
026    import org.jetbrains.kotlin.lexer.JetTokens;
027    import org.jetbrains.kotlin.psi.*;
028    import org.jetbrains.kotlin.resolve.annotations.*;
029    import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage;
030    import org.jetbrains.kotlin.resolve.calls.CallResolver;
031    import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
032    import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
033    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
034    import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
035    import org.jetbrains.kotlin.resolve.constants.ConstantValue;
036    import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
037    import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
038    import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor;
039    import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationsContextImpl;
040    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
041    import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
042    import org.jetbrains.kotlin.storage.StorageManager;
043    import org.jetbrains.kotlin.types.ErrorUtils;
044    import org.jetbrains.kotlin.types.JetType;
045    
046    import javax.inject.Inject;
047    import java.util.ArrayList;
048    import java.util.List;
049    
050    import static org.jetbrains.kotlin.diagnostics.Errors.NOT_AN_ANNOTATION_CLASS;
051    import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
052    
053    public class AnnotationResolver {
054        @NotNull private final CallResolver callResolver;
055        @NotNull private final StorageManager storageManager;
056        @NotNull private TypeResolver typeResolver;
057        @NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
058    
059        @NotNull private final List<AnnotationDescriptor> modifiersAnnotations;
060    
061        public AnnotationResolver(
062                @NotNull CallResolver callResolver,
063                @NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
064                @NotNull StorageManager storageManager,
065                @NotNull KotlinBuiltIns kotlinBuiltIns
066        ) {
067            this.callResolver = callResolver;
068            this.constantExpressionEvaluator = constantExpressionEvaluator;
069            this.storageManager = storageManager;
070    
071            modifiersAnnotations = AnnotationsPackage.buildMigrationAnnotationDescriptors(kotlinBuiltIns);
072        }
073    
074    
075        // component dependency cycle
076        @Inject
077        public void setTypeResolver(@NotNull TypeResolver typeResolver) {
078            this.typeResolver = typeResolver;
079        }
080    
081        @NotNull
082        public Annotations resolveAnnotationsWithoutArguments(
083                @NotNull LexicalScope scope,
084                @Nullable JetModifierList modifierList,
085                @NotNull BindingTrace trace
086        ) {
087            return resolveAnnotations(scope, modifierList, trace, false);
088        }
089    
090        @NotNull
091        public Annotations resolveAnnotationsWithArguments(
092                @NotNull LexicalScope scope,
093                @Nullable JetModifierList modifierList,
094                @NotNull BindingTrace trace
095        ) {
096            return resolveAnnotations(scope, modifierList, trace, true);
097        }
098    
099        @NotNull
100        public Annotations resolveAnnotationsWithoutArguments(
101                @NotNull LexicalScope scope,
102                @NotNull List<JetAnnotationEntry> annotationEntries,
103                @NotNull BindingTrace trace
104        ) {
105            return resolveAnnotationEntries(scope, annotationEntries, trace, false);
106        }
107    
108        @NotNull
109        public Annotations resolveAnnotationsWithArguments(
110                @NotNull LexicalScope scope,
111                @NotNull List<JetAnnotationEntry> annotationEntries,
112                @NotNull BindingTrace trace
113        ) {
114            return resolveAnnotationEntries(scope, annotationEntries, trace, true);
115        }
116    
117        private Annotations resolveAnnotations(
118                @NotNull LexicalScope scope,
119                @Nullable JetModifierList modifierList,
120                @NotNull BindingTrace trace,
121                boolean shouldResolveArguments
122        ) {
123            if (modifierList == null) {
124                return Annotations.EMPTY;
125            }
126    
127            List<JetAnnotationEntry> annotationEntryElements = modifierList.getAnnotationEntries();
128    
129            return resolveAndAppendAnnotationsFromModifiers(
130                    resolveAnnotationEntries(scope, annotationEntryElements, trace, shouldResolveArguments),
131                    modifierList
132            );
133        }
134    
135        @NotNull
136        public Annotations resolveAndAppendAnnotationsFromModifiers(
137                @NotNull Annotations annotations,
138                @NotNull JetModifierList modifierList
139        ) {
140            List<AnnotationDescriptor> annotationFromModifiers = new ArrayList<AnnotationDescriptor>();
141    
142            for (int i = 0; i < JetTokens.ANNOTATION_MODIFIERS_KEYWORDS_ARRAY.length; i++) {
143                JetModifierKeywordToken modifier = JetTokens.ANNOTATION_MODIFIERS_KEYWORDS_ARRAY[i];
144                if (modifierList.hasModifier(modifier)) {
145                    annotationFromModifiers.add(modifiersAnnotations.get(i));
146                }
147            }
148    
149            if (annotationFromModifiers.isEmpty()) return annotations;
150    
151            return new CompositeAnnotations(annotations, new AnnotationsImpl(annotationFromModifiers));
152        }
153    
154        private Annotations resolveAnnotationEntries(
155                @NotNull LexicalScope scope,
156                @NotNull List<JetAnnotationEntry> annotationEntryElements,
157                @NotNull BindingTrace trace,
158                boolean shouldResolveArguments
159        ) {
160            if (annotationEntryElements.isEmpty()) return Annotations.EMPTY;
161            List<AnnotationWithTarget> result = new ArrayList<AnnotationWithTarget>(0);
162    
163            for (JetAnnotationEntry entryElement : annotationEntryElements) {
164                AnnotationDescriptor descriptor = trace.get(BindingContext.ANNOTATION, entryElement);
165                if (descriptor == null) {
166                    descriptor = new LazyAnnotationDescriptor(new LazyAnnotationsContextImpl(this, storageManager, trace, scope), entryElement);
167                }
168                if (shouldResolveArguments) {
169                    ForceResolveUtil.forceResolveAllContents(descriptor);
170                }
171    
172                JetAnnotationUseSiteTarget target = entryElement.getUseSiteTarget();
173                if (target != null) {
174                    result.add(new AnnotationWithTarget(descriptor, target.getAnnotationUseSiteTarget()));
175                }
176                else {
177                    result.add(new AnnotationWithTarget(descriptor, null));
178                }
179            }
180            return AnnotationsImpl.create(result);
181        }
182    
183        @NotNull
184        public JetType resolveAnnotationType(@NotNull LexicalScope scope, @NotNull JetAnnotationEntry entryElement) {
185            JetTypeReference typeReference = entryElement.getTypeReference();
186            if (typeReference == null) {
187                return ErrorUtils.createErrorType("No type reference: " + entryElement.getText());
188            }
189    
190            JetType type = typeResolver.resolveType(scope, typeReference, new BindingTraceContext(), true);
191            if (!(type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) {
192                return ErrorUtils.createErrorType("Not an annotation: " + type);
193            }
194            return type;
195        }
196    
197        public static void checkAnnotationType(
198                @NotNull JetAnnotationEntry entryElement,
199                @NotNull BindingTrace trace,
200                @NotNull OverloadResolutionResults<FunctionDescriptor> results
201        ) {
202            if (!results.isSingleResult()) return;
203            FunctionDescriptor descriptor = results.getResultingDescriptor();
204            if (!ErrorUtils.isError(descriptor)) {
205                if (descriptor instanceof ConstructorDescriptor) {
206                    ConstructorDescriptor constructor = (ConstructorDescriptor)descriptor;
207                    ClassDescriptor classDescriptor = constructor.getContainingDeclaration();
208                    if (classDescriptor.getKind() != ClassKind.ANNOTATION_CLASS) {
209                        trace.report(NOT_AN_ANNOTATION_CLASS.on(entryElement, classDescriptor));
210                    }
211                }
212                else {
213                    trace.report(NOT_AN_ANNOTATION_CLASS.on(entryElement, descriptor));
214                }
215            }
216        }
217    
218        @NotNull
219        public OverloadResolutionResults<FunctionDescriptor> resolveAnnotationCall(
220                JetAnnotationEntry annotationEntry,
221                LexicalScope scope,
222                BindingTrace trace
223        ) {
224            return callResolver.resolveFunctionCall(
225                    trace, scope,
226                    CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, annotationEntry),
227                    NO_EXPECTED_TYPE,
228                    DataFlowInfo.EMPTY,
229                    true
230            );
231        }
232    
233        public static void reportUnsupportedAnnotationForTypeParameter(@NotNull JetTypeParameter jetTypeParameter, @NotNull BindingTrace trace) {
234            JetModifierList modifierList = jetTypeParameter.getModifierList();
235            if (modifierList == null) return;
236    
237            for (JetAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) {
238                trace.report(Errors.UNSUPPORTED.on(annotationEntry, "Annotations for type parameters are not supported yet"));
239            }
240        }
241    
242        @Nullable
243        public ConstantValue<?> getAnnotationArgumentValue(
244                @NotNull BindingTrace trace,
245                @NotNull ValueParameterDescriptor valueParameter,
246                @NotNull ResolvedValueArgument resolvedArgument
247        ) {
248            return constantExpressionEvaluator.getAnnotationArgumentValue(trace, valueParameter, resolvedArgument);
249        }
250    }