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 com.google.common.collect.Lists;
020 import com.intellij.openapi.util.Pair;
021 import kotlin.KotlinPackage;
022 import kotlin.jvm.functions.Function1;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
026 import org.jetbrains.kotlin.descriptors.*;
027 import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
028 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
029 import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl;
030 import org.jetbrains.kotlin.diagnostics.Errors;
031 import org.jetbrains.kotlin.psi.*;
032 import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver;
033 import org.jetbrains.kotlin.resolve.calls.CallResolver;
034 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
035 import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker;
036 import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
037 import org.jetbrains.kotlin.resolve.calls.checkers.CompositeChecker;
038 import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
039 import org.jetbrains.kotlin.resolve.calls.context.SimpleResolutionContext;
040 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
041 import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
042 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
043 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
044 import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
045 import org.jetbrains.kotlin.resolve.constants.ArrayValue;
046 import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
047 import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant;
048 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
049 import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor;
050 import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationsContextImpl;
051 import org.jetbrains.kotlin.resolve.scopes.JetScope;
052 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
053 import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator;
054 import org.jetbrains.kotlin.storage.StorageManager;
055 import org.jetbrains.kotlin.types.ErrorUtils;
056 import org.jetbrains.kotlin.types.JetType;
057 import org.jetbrains.kotlin.types.checker.JetTypeChecker;
058
059 import javax.inject.Inject;
060 import java.util.HashMap;
061 import java.util.List;
062 import java.util.Map;
063
064 import static org.jetbrains.kotlin.diagnostics.Errors.DEPRECATED_ANNOTATION_SYNTAX;
065 import static org.jetbrains.kotlin.diagnostics.Errors.NOT_AN_ANNOTATION_CLASS;
066 import static org.jetbrains.kotlin.resolve.BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT;
067 import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
068
069 public class AnnotationResolver {
070
071 private CallResolver callResolver;
072 private StorageManager storageManager;
073 private TypeResolver typeResolver;
074
075 @Inject
076 public void setCallResolver(CallResolver callResolver) {
077 this.callResolver = callResolver;
078 }
079
080 @Inject
081 public void setStorageManager(StorageManager storageManager) {
082 this.storageManager = storageManager;
083 }
084
085 @Inject
086 public void setTypeResolver(TypeResolver typeResolver) {
087 this.typeResolver = typeResolver;
088 }
089
090 @NotNull
091 public Annotations resolveAnnotationsWithoutArguments(
092 @NotNull JetScope scope,
093 @Nullable JetModifierList modifierList,
094 @NotNull BindingTrace trace
095 ) {
096 return resolveAnnotations(scope, modifierList, trace, false);
097 }
098
099 @NotNull
100 public Annotations resolveAnnotationsWithArguments(
101 @NotNull JetScope scope,
102 @Nullable JetModifierList modifierList,
103 @NotNull BindingTrace trace
104 ) {
105 return resolveAnnotations(scope, modifierList, trace, true);
106 }
107
108 @NotNull
109 public Annotations resolveAnnotationsWithArguments(
110 @NotNull JetScope 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 JetScope scope,
119 @Nullable JetModifierList modifierList,
120 @NotNull BindingTrace trace,
121 boolean shouldResolveArguments
122 ) {
123 if (modifierList == null) {
124 return Annotations.EMPTY;
125 }
126 reportDeprecatedAnnotationSyntax(modifierList.getAnnotations(), trace);
127
128 List<JetAnnotationEntry> annotationEntryElements = modifierList.getAnnotationEntries();
129
130 return resolveAnnotationEntries(scope, annotationEntryElements, trace, shouldResolveArguments);
131 }
132
133 private Annotations resolveAnnotationEntries(
134 @NotNull JetScope scope,
135 @NotNull List<JetAnnotationEntry> annotationEntryElements,
136 @NotNull BindingTrace trace,
137 boolean shouldResolveArguments
138 ) {
139 if (annotationEntryElements.isEmpty()) return Annotations.EMPTY;
140 List<AnnotationDescriptor> result = Lists.newArrayList();
141 for (JetAnnotationEntry entryElement : annotationEntryElements) {
142 AnnotationDescriptor descriptor = trace.get(BindingContext.ANNOTATION, entryElement);
143 if (descriptor == null) {
144 descriptor = new LazyAnnotationDescriptor(new LazyAnnotationsContextImpl(this, storageManager, trace, scope), entryElement);
145 }
146 if (shouldResolveArguments) {
147 resolveAnnotationArguments(entryElement, trace);
148 }
149
150 result.add(descriptor);
151 }
152 return new AnnotationsImpl(result);
153 }
154
155 @NotNull
156 public JetType resolveAnnotationType(@NotNull JetScope scope, @NotNull JetAnnotationEntry entryElement) {
157 JetTypeReference typeReference = entryElement.getTypeReference();
158 if (typeReference == null) {
159 return ErrorUtils.createErrorType("No type reference: " + entryElement.getText());
160 }
161
162 JetType type = typeResolver.resolveType(scope, typeReference, new BindingTraceContext(), true);
163 if (!(type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) {
164 return ErrorUtils.createErrorType("Not an annotation: " + type);
165 }
166 return type;
167 }
168
169 public static void checkAnnotationType(
170 @NotNull JetAnnotationEntry entryElement,
171 @NotNull BindingTrace trace,
172 @NotNull OverloadResolutionResults<FunctionDescriptor> results
173 ) {
174 if (!results.isSingleResult()) return;
175 FunctionDescriptor descriptor = results.getResultingDescriptor();
176 if (!ErrorUtils.isError(descriptor)) {
177 if (descriptor instanceof ConstructorDescriptor) {
178 ConstructorDescriptor constructor = (ConstructorDescriptor)descriptor;
179 ClassDescriptor classDescriptor = constructor.getContainingDeclaration();
180 if (classDescriptor.getKind() != ClassKind.ANNOTATION_CLASS) {
181 trace.report(NOT_AN_ANNOTATION_CLASS.on(entryElement, classDescriptor));
182 }
183 }
184 else {
185 trace.report(NOT_AN_ANNOTATION_CLASS.on(entryElement, descriptor));
186 }
187 }
188 }
189
190 @NotNull
191 public OverloadResolutionResults<FunctionDescriptor> resolveAnnotationCall(
192 JetAnnotationEntry annotationEntry,
193 JetScope scope,
194 BindingTrace trace
195 ) {
196 return callResolver.resolveFunctionCall(
197 trace, scope,
198 CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, annotationEntry),
199 NO_EXPECTED_TYPE,
200 DataFlowInfo.EMPTY,
201 true
202 );
203 }
204
205 public static void resolveAnnotationsArguments(@Nullable JetModifierList modifierList, @NotNull BindingTrace trace) {
206 if (modifierList == null) {
207 return;
208 }
209
210 for (JetAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) {
211 resolveAnnotationArguments(annotationEntry, trace);
212 }
213 }
214
215 public static void resolveAnnotationsArguments(@NotNull Annotations annotations, @NotNull BindingTrace trace) {
216 for (AnnotationDescriptor annotationDescriptor : annotations) {
217 JetAnnotationEntry annotationEntry = trace.getBindingContext().get(ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT, annotationDescriptor);
218 assert annotationEntry != null : "Cannot find annotation entry: " + annotationDescriptor;
219 resolveAnnotationArguments(annotationEntry, trace);
220 }
221 }
222
223 private static void resolveAnnotationArguments(
224 @NotNull JetAnnotationEntry annotationEntry,
225 @NotNull BindingTrace trace
226 ) {
227 AnnotationDescriptor annotationDescriptor = trace.getBindingContext().get(BindingContext.ANNOTATION, annotationEntry);
228 assert annotationDescriptor != null : "Annotation descriptor should be created before resolving arguments for " + annotationEntry.getText();
229 if (annotationDescriptor instanceof LazyAnnotationDescriptor) {
230 ((LazyAnnotationDescriptor) annotationDescriptor).forceResolveAllContents();
231 }
232 }
233
234 @NotNull
235 public static Map<ValueParameterDescriptor, CompileTimeConstant<?>> resolveAnnotationArguments(
236 @NotNull ResolvedCall<?> resolvedCall,
237 @NotNull BindingTrace trace
238 ) {
239 Map<ValueParameterDescriptor, CompileTimeConstant<?>> arguments = new HashMap<ValueParameterDescriptor, CompileTimeConstant<?>>();
240 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> descriptorToArgument : resolvedCall.getValueArguments().entrySet()) {
241 ValueParameterDescriptor parameterDescriptor = descriptorToArgument.getKey();
242 ResolvedValueArgument resolvedArgument = descriptorToArgument.getValue();
243
244 CompileTimeConstant<?> value = getAnnotationArgumentValue(trace, parameterDescriptor, resolvedArgument);
245 if (value != null) {
246 arguments.put(parameterDescriptor, value);
247 }
248 }
249 return arguments;
250 }
251
252 @Nullable
253 public static CompileTimeConstant<?> getAnnotationArgumentValue(
254 BindingTrace trace,
255 ValueParameterDescriptor parameterDescriptor,
256 ResolvedValueArgument resolvedArgument
257 ) {
258 JetType varargElementType = parameterDescriptor.getVarargElementType();
259 boolean argumentsAsVararg = varargElementType != null && !hasSpread(resolvedArgument);
260 List<CompileTimeConstant<?>> constants = resolveValueArguments(
261 resolvedArgument, argumentsAsVararg ? varargElementType : parameterDescriptor.getType(), trace);
262
263 if (argumentsAsVararg) {
264
265 boolean usesVariableAsConstant = KotlinPackage.any(constants, new Function1<CompileTimeConstant<?>, Boolean>() {
266 @Override
267 public Boolean invoke(CompileTimeConstant<?> constant) {
268 return constant.usesVariableAsConstant();
269 }
270 });
271
272 if (parameterDescriptor.declaresDefaultValue() && constants.isEmpty()) return null;
273
274 return new ArrayValue(constants, parameterDescriptor.getType(), true, usesVariableAsConstant);
275 }
276 else {
277 // we should actually get only one element, but just in case of getting many, we take the last one
278 return !constants.isEmpty() ? KotlinPackage.last(constants) : null;
279 }
280 }
281
282 private static void checkCompileTimeConstant(
283 @NotNull JetExpression argumentExpression,
284 @NotNull JetType expectedType,
285 @NotNull BindingTrace trace
286 ) {
287 JetType expressionType = trace.getType(argumentExpression);
288
289 if (expressionType == null || !JetTypeChecker.DEFAULT.isSubtypeOf(expressionType, expectedType)) {
290 // TYPE_MISMATCH should be reported otherwise
291 return;
292 }
293
294 // array(1, <!>null<!>, 3) - error should be reported on inner expression
295 if (argumentExpression instanceof JetCallExpression) {
296 Pair<List<JetExpression>, JetType> arrayArgument = getArgumentExpressionsForArrayCall((JetCallExpression) argumentExpression, trace);
297 if (arrayArgument != null) {
298 for (JetExpression expression : arrayArgument.getFirst()) {
299 checkCompileTimeConstant(expression, arrayArgument.getSecond(), trace);
300 }
301 }
302 }
303
304 CompileTimeConstant<?> constant = ConstantExpressionEvaluator.getConstant(argumentExpression, trace.getBindingContext());
305 if (constant != null && constant.canBeUsedInAnnotations()) {
306 return;
307 }
308
309 ClassifierDescriptor descriptor = expressionType.getConstructor().getDeclarationDescriptor();
310 if (descriptor != null && DescriptorUtils.isEnumClass(descriptor)) {
311 trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST.on(argumentExpression));
312 }
313 else if (descriptor instanceof ClassDescriptor && DescriptorUtils.isJavaLangClass((ClassDescriptor) descriptor)) {
314 trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_CLASS_LITERAL.on(argumentExpression));
315 }
316 else if (descriptor instanceof ClassDescriptor && KotlinBuiltIns.isKClass((ClassDescriptor) descriptor)) {
317 trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression));
318 }
319 else {
320 trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_CONST.on(argumentExpression));
321 }
322 }
323
324 @Nullable
325 private static Pair<List<JetExpression>, JetType> getArgumentExpressionsForArrayCall(
326 @NotNull JetCallExpression expression,
327 @NotNull BindingTrace trace
328 ) {
329 ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(expression, trace.getBindingContext());
330 if (resolvedCall == null || !CompileTimeConstantUtils.isArrayMethodCall(resolvedCall)) {
331 return null;
332 }
333
334 assert resolvedCall.getValueArguments().size() == 1 : "Array function should have only one vararg parameter";
335 Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> argumentEntry = resolvedCall.getValueArguments().entrySet().iterator().next();
336
337 List<JetExpression> result = Lists.newArrayList();
338 JetType elementType = argumentEntry.getKey().getVarargElementType();
339 for (ValueArgument valueArgument : argumentEntry.getValue().getArguments()) {
340 JetExpression valueArgumentExpression = valueArgument.getArgumentExpression();
341 if (valueArgumentExpression != null) {
342 if (elementType != null) {
343 result.add(valueArgumentExpression);
344 }
345 }
346 }
347 return new Pair<List<JetExpression>, JetType>(result, elementType);
348 }
349
350 private static boolean hasSpread(@NotNull ResolvedValueArgument argument) {
351 List<ValueArgument> arguments = argument.getArguments();
352 return arguments.size() == 1 && arguments.get(0).getSpreadElement() != null;
353 }
354
355 @NotNull
356 private static List<CompileTimeConstant<?>> resolveValueArguments(
357 @NotNull ResolvedValueArgument resolvedValueArgument,
358 @NotNull JetType expectedType,
359 @NotNull BindingTrace trace
360 ) {
361 List<CompileTimeConstant<?>> constants = Lists.newArrayList();
362 for (ValueArgument argument : resolvedValueArgument.getArguments()) {
363 JetExpression argumentExpression = argument.getArgumentExpression();
364 if (argumentExpression != null) {
365 CompileTimeConstant<?> constant = ConstantExpressionEvaluator.evaluate(argumentExpression, trace, expectedType);
366 if (constant instanceof IntegerValueTypeConstant) {
367 JetType defaultType = ((IntegerValueTypeConstant) constant).getType(expectedType);
368 SimpleResolutionContext context =
369 new SimpleResolutionContext(trace, JetScope.Empty.INSTANCE$, NO_EXPECTED_TYPE, DataFlowInfo.EMPTY,
370 ContextDependency.INDEPENDENT,
371 new CompositeChecker(Lists.<CallChecker>newArrayList()),
372 SymbolUsageValidator.Empty,
373 new AdditionalTypeChecker.Composite(Lists.<AdditionalTypeChecker>newArrayList()),
374 StatementFilter.NONE);
375 ArgumentTypeResolver.updateNumberType(defaultType, argumentExpression, context);
376 }
377 if (constant != null) {
378 constants.add(constant);
379 }
380 checkCompileTimeConstant(argumentExpression, expectedType, trace);
381 }
382 }
383 return constants;
384 }
385
386 public static void reportUnsupportedAnnotationForTypeParameter(@NotNull JetTypeParameter jetTypeParameter, @NotNull BindingTrace trace) {
387 JetModifierList modifierList = jetTypeParameter.getModifierList();
388 if (modifierList == null) return;
389
390 for (JetAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) {
391 trace.report(Errors.UNSUPPORTED.on(annotationEntry, "Annotations for type parameters are not supported yet"));
392 }
393 }
394
395 public static void reportDeprecatedAnnotationSyntax(@NotNull List<JetAnnotation> annotations, @NotNull BindingTrace trace) {
396 for (JetAnnotation annotation : annotations) {
397 reportDeprecatedAnnotationSyntax(annotation, trace);
398 }
399 }
400
401 public static void reportDeprecatedAnnotationSyntax(@NotNull JetAnnotation annotation, @NotNull BindingTrace trace) {
402 if (annotation.isDeprecated()) {
403 trace.report(DEPRECATED_ANNOTATION_SYNTAX.on(annotation));
404 }
405 }
406 }