001 /*
002 * Copyright 2010-2013 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.jet.lang.resolve;
018
019 import com.google.common.collect.Lists;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.jet.lang.descriptors.*;
023 import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
024 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
025 import org.jetbrains.jet.lang.diagnostics.Errors;
026 import org.jetbrains.jet.lang.psi.*;
027 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
028 import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
029 import org.jetbrains.jet.lang.resolve.calls.CallResolver;
030 import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
031 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
032 import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
033 import org.jetbrains.jet.lang.resolve.constants.*;
034 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
035 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
036 import org.jetbrains.jet.lang.types.ErrorUtils;
037 import org.jetbrains.jet.lang.types.JetType;
038 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
039 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
040
041 import javax.inject.Inject;
042 import java.util.Collections;
043 import java.util.List;
044 import java.util.Map;
045
046 import static org.jetbrains.jet.lang.resolve.BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT;
047 import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
048
049 public class AnnotationResolver {
050
051 private ExpressionTypingServices expressionTypingServices;
052 private CallResolver callResolver;
053
054 @Inject
055 public void setExpressionTypingServices(ExpressionTypingServices expressionTypingServices) {
056 this.expressionTypingServices = expressionTypingServices;
057 }
058
059 @Inject
060 public void setCallResolver(CallResolver callResolver) {
061 this.callResolver = callResolver;
062 }
063
064 @NotNull
065 public List<AnnotationDescriptor> resolveAnnotations(
066 @NotNull JetScope scope,
067 @Nullable JetModifierList modifierList,
068 @NotNull BindingTrace trace)
069 {
070 return resolveAnnotations(scope, modifierList, trace, false);
071 }
072
073 @NotNull
074 public List<AnnotationDescriptor> resolveAnnotationsWithArguments(
075 @NotNull JetScope scope,
076 @Nullable JetModifierList modifierList,
077 @NotNull BindingTrace trace
078 ) {
079 return resolveAnnotations(scope, modifierList, trace, true);
080 }
081
082 private List<AnnotationDescriptor> resolveAnnotations(
083 @NotNull JetScope scope,
084 @Nullable JetModifierList modifierList,
085 @NotNull BindingTrace trace,
086 boolean shouldResolveArguments
087 ) {
088 if (modifierList == null) {
089 return Collections.emptyList();
090 }
091 List<JetAnnotationEntry> annotationEntryElements = modifierList.getAnnotationEntries();
092
093 if (annotationEntryElements.isEmpty()) return Collections.emptyList();
094 List<AnnotationDescriptor> result = Lists.newArrayList();
095 for (JetAnnotationEntry entryElement : annotationEntryElements) {
096 AnnotationDescriptor descriptor = new AnnotationDescriptor();
097 resolveAnnotationStub(scope, entryElement, descriptor, trace);
098 trace.record(BindingContext.ANNOTATION, entryElement, descriptor);
099 if (shouldResolveArguments) {
100 resolveAnnotationArguments(entryElement, scope, trace);
101 }
102 result.add(descriptor);
103 }
104 return result;
105 }
106
107 public void resolveAnnotationStub(
108 @NotNull JetScope scope,
109 @NotNull JetAnnotationEntry entryElement,
110 @NotNull AnnotationDescriptor annotationDescriptor,
111 @NotNull BindingTrace trace
112 ) {
113 TemporaryBindingTrace temporaryBindingTrace = new TemporaryBindingTrace(trace, "Trace for resolve annotation type");
114 OverloadResolutionResults<FunctionDescriptor> results = resolveAnnotationCall(entryElement, scope, temporaryBindingTrace);
115 if (results.isSuccess()) {
116 FunctionDescriptor descriptor = results.getResultingDescriptor();
117 if (!ErrorUtils.isError(descriptor)) {
118 if (descriptor instanceof ConstructorDescriptor) {
119 ConstructorDescriptor constructor = (ConstructorDescriptor)descriptor;
120 ClassDescriptor classDescriptor = constructor.getContainingDeclaration();
121 if (classDescriptor.getKind() != ClassKind.ANNOTATION_CLASS) {
122 trace.report(Errors.NOT_AN_ANNOTATION_CLASS.on(entryElement, classDescriptor.getName().asString()));
123 }
124 }
125 else {
126 trace.report(Errors.NOT_AN_ANNOTATION_CLASS.on(entryElement, descriptor.getName().asString()));
127 }
128 }
129 JetType annotationType = results.getResultingDescriptor().getReturnType();
130 annotationDescriptor.setAnnotationType(annotationType);
131 }
132 else {
133 annotationDescriptor.setAnnotationType(ErrorUtils.createErrorType("Unresolved annotation type"));
134 }
135 }
136
137 private OverloadResolutionResults<FunctionDescriptor> resolveAnnotationCall(
138 JetAnnotationEntry annotationEntry,
139 JetScope scope,
140 BindingTrace trace
141 ) {
142 return callResolver.resolveFunctionCall(
143 trace, scope,
144 CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, annotationEntry),
145 NO_EXPECTED_TYPE,
146 DataFlowInfo.EMPTY);
147 }
148
149 public void resolveAnnotationsArguments(@NotNull JetScope scope, @Nullable JetModifierList modifierList, @NotNull BindingTrace trace) {
150 if (modifierList == null) {
151 return;
152 }
153
154 for (JetAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) {
155 resolveAnnotationArguments(annotationEntry, scope, trace);
156 }
157 }
158
159 public void resolveAnnotationsArguments(@NotNull Annotated descriptor, @NotNull BindingTrace trace, @NotNull JetScope scope) {
160 for (AnnotationDescriptor annotationDescriptor : descriptor.getAnnotations()) {
161 JetAnnotationEntry annotationEntry = trace.getBindingContext().get(ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT, annotationDescriptor);
162 assert annotationEntry != null : "Cannot find annotation entry: " + annotationDescriptor;
163 resolveAnnotationArguments(annotationEntry, scope, trace);
164 }
165 }
166
167 private void resolveAnnotationArguments(
168 @NotNull JetAnnotationEntry annotationEntry,
169 @NotNull JetScope scope,
170 @NotNull BindingTrace trace
171 ) {
172 OverloadResolutionResults<FunctionDescriptor> results = resolveAnnotationCall(annotationEntry, scope, trace);
173 if (results.isSuccess()) {
174 AnnotationDescriptor annotationDescriptor = trace.getBindingContext().get(BindingContext.ANNOTATION, annotationEntry);
175 assert annotationDescriptor != null : "Annotation descriptor should be created before resolving arguments for " + annotationEntry.getText();
176 resolveAnnotationArgument(annotationDescriptor, results.getResultingCall(), trace);
177 }
178 }
179
180 private void resolveAnnotationArgument(
181 @NotNull AnnotationDescriptor annotationDescriptor,
182 @NotNull ResolvedCall<? extends CallableDescriptor> call,
183 @NotNull BindingTrace trace
184 ) {
185 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> descriptorToArgument :
186 call.getValueArguments().entrySet()) {
187 ValueParameterDescriptor parameterDescriptor = descriptorToArgument.getKey();
188
189 JetType varargElementType = parameterDescriptor.getVarargElementType();
190 List<CompileTimeConstant<?>> constants = resolveValueArguments(descriptorToArgument.getValue(), parameterDescriptor.getType(), trace);
191 if (varargElementType == null) {
192 for (CompileTimeConstant<?> constant : constants) {
193 annotationDescriptor.setValueArgument(parameterDescriptor, constant);
194 }
195 }
196 else {
197 JetType arrayType = KotlinBuiltIns.getInstance().getPrimitiveArrayJetTypeByPrimitiveJetType(varargElementType);
198 if (arrayType == null) {
199 arrayType = KotlinBuiltIns.getInstance().getArrayType(varargElementType);
200 }
201 annotationDescriptor.setValueArgument(parameterDescriptor, new ArrayValue(constants, arrayType));
202 }
203 }
204 }
205
206 @NotNull
207 private List<CompileTimeConstant<?>> resolveValueArguments(
208 @NotNull ResolvedValueArgument resolvedValueArgument,
209 @NotNull JetType expectedType,
210 @NotNull BindingTrace trace
211 ) {
212 List<CompileTimeConstant<?>> constants = Lists.newArrayList();
213 for (ValueArgument argument : resolvedValueArgument.getArguments()) {
214 JetExpression argumentExpression = argument.getArgumentExpression();
215 if (argumentExpression != null) {
216 CompileTimeConstant<?> constant = resolveAnnotationArgument(argumentExpression, expectedType, trace);
217 if (constant != null) {
218 constants.add(constant);
219 }
220 }
221 }
222 return constants;
223 }
224
225 @Nullable
226 private CompileTimeConstant<?> resolveAnnotationArgument(@NotNull JetExpression expression, @NotNull final JetType expectedType, final BindingTrace trace) {
227 JetVisitor<CompileTimeConstant<?>, Void> visitor = new JetVisitor<CompileTimeConstant<?>, Void>() {
228 @Override
229 public CompileTimeConstant<?> visitConstantExpression(JetConstantExpression expression, Void nothing) {
230 JetType type = expressionTypingServices.getType(JetScope.EMPTY, expression, expectedType, DataFlowInfo.EMPTY, trace);
231 if (type == null) {
232 // TODO:
233 // trace.report(ANNOTATION_PARAMETER_SHOULD_BE_CONSTANT.on(expression));
234 }
235 return trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
236 }
237
238
239 // @Override
240 // public CompileTimeConstant visitAnnotation(JetAnnotation annotation, Void nothing) {
241 // super.visitAnnotation(annotation, null); // TODO
242 // }
243 //
244 // @Override
245 // public CompileTimeConstant visitAnnotationEntry(JetAnnotationEntry annotationEntry, Void nothing) {
246 // return super.visitAnnotationEntry(annotationEntry, null); // TODO
247 // }
248
249 @Override
250 public CompileTimeConstant<?> visitParenthesizedExpression(JetParenthesizedExpression expression, Void nothing) {
251 JetExpression innerExpression = expression.getExpression();
252 if (innerExpression == null) return null;
253 return innerExpression.accept(this, null);
254 }
255
256 @Override
257 public CompileTimeConstant<?> visitStringTemplateExpression(JetStringTemplateExpression expression,
258 Void nothing) {
259 return trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
260 }
261
262 @Override
263 public CompileTimeConstant<?> visitSimpleNameExpression(JetSimpleNameExpression expression, Void data) {
264 ResolvedCall<? extends CallableDescriptor> resolvedCall =
265 trace.getBindingContext().get(BindingContext.RESOLVED_CALL, expression);
266 if (resolvedCall != null) {
267 CallableDescriptor callableDescriptor = resolvedCall.getResultingDescriptor();
268 if (callableDescriptor instanceof PropertyDescriptor) {
269 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) callableDescriptor;
270 if (isEnumProperty(propertyDescriptor)) {
271 return new EnumValue(propertyDescriptor);
272 }
273 }
274 }
275 return null;
276 }
277
278 @Override
279 public CompileTimeConstant<?> visitQualifiedExpression(JetQualifiedExpression expression, Void data) {
280 JetExpression selectorExpression = expression.getSelectorExpression();
281 if (selectorExpression != null) {
282 return selectorExpression.accept(this, null);
283 }
284 return super.visitQualifiedExpression(expression, data);
285 }
286
287 @Override
288 public CompileTimeConstant<?> visitCallExpression(JetCallExpression expression, Void data) {
289 ResolvedCall<? extends CallableDescriptor> call =
290 trace.getBindingContext().get(BindingContext.RESOLVED_CALL, (expression).getCalleeExpression());
291 if (call != null) {
292 CallableDescriptor resultingDescriptor = call.getResultingDescriptor();
293 if (AnnotationUtils.isArrayMethodCall(call)) {
294 JetType type = resultingDescriptor.getValueParameters().iterator().next().getVarargElementType();
295 List<CompileTimeConstant<?>> arguments = Lists.newArrayList();
296 for (ResolvedValueArgument descriptorToArgument : call.getValueArguments().values()) {
297 arguments.addAll(resolveValueArguments(descriptorToArgument, type, trace));
298 }
299 return new ArrayValue(arguments, resultingDescriptor.getReturnType());
300 }
301
302 if (resultingDescriptor instanceof ConstructorDescriptor) {
303 JetType constructorReturnType = resultingDescriptor.getReturnType();
304 assert constructorReturnType != null : "Constructor should have return type";
305 if (DescriptorUtils.isAnnotationClass(constructorReturnType.getConstructor().getDeclarationDescriptor())) {
306 AnnotationDescriptor descriptor = new AnnotationDescriptor();
307 descriptor.setAnnotationType(constructorReturnType);
308 resolveAnnotationArgument(descriptor, call, trace);
309 return new AnnotationValue(descriptor);
310 }
311 }
312
313 if (AnnotationUtils.isJavaClassMethodCall(call)) {
314 return new JavaClassValue(resultingDescriptor.getReturnType());
315 }
316 }
317 return null;
318 }
319
320 @Override
321 public CompileTimeConstant<?> visitJetElement(JetElement element, Void nothing) {
322 // TODO:
323 //trace.report(ANNOTATION_PARAMETER_SHOULD_BE_CONSTANT.on(element));
324 return null;
325 }
326 };
327 return expression.accept(visitor, null);
328 }
329
330 private static boolean isEnumProperty(@NotNull PropertyDescriptor descriptor) {
331 if (DescriptorUtils.isKindOf(descriptor.getType(), ClassKind.ENUM_CLASS)) {
332 DeclarationDescriptor enumClassObject = descriptor.getContainingDeclaration();
333 if (DescriptorUtils.isKindOf(enumClassObject, ClassKind.CLASS_OBJECT)) {
334 return DescriptorUtils.isKindOf(enumClassObject.getContainingDeclaration(), ClassKind.ENUM_CLASS);
335 }
336 }
337 return false;
338 }
339
340 @NotNull
341 public List<AnnotationDescriptor> getResolvedAnnotations(@Nullable JetModifierList modifierList, BindingTrace trace) {
342 if (modifierList == null) {
343 return Collections.emptyList();
344 }
345 return getResolvedAnnotations(modifierList.getAnnotationEntries(), trace);
346 }
347
348 @SuppressWarnings("MethodMayBeStatic")
349 @NotNull
350 public List<AnnotationDescriptor> getResolvedAnnotations(List<JetAnnotationEntry> annotations, BindingTrace trace) {
351 List<AnnotationDescriptor> result = Lists.newArrayList();
352 for (JetAnnotationEntry annotation : annotations) {
353 AnnotationDescriptor annotationDescriptor = trace.get(BindingContext.ANNOTATION, annotation);
354 if (annotationDescriptor == null) {
355 // TODO: Unresolved annotation
356 annotationDescriptor = new AnnotationDescriptor();
357 annotationDescriptor.setAnnotationType(ErrorUtils.createErrorType("Unresolved annotation type"));
358
359 trace.record(BindingContext.ANNOTATION, annotation, annotationDescriptor);
360 }
361
362 result.add(annotationDescriptor);
363 }
364 return result;
365 }
366 }