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 017package org.jetbrains.jet.lang.resolve; 018 019import com.google.common.collect.Lists; 020import org.jetbrains.annotations.NotNull; 021import org.jetbrains.annotations.Nullable; 022import org.jetbrains.jet.lang.descriptors.*; 023import org.jetbrains.jet.lang.descriptors.annotations.Annotated; 024import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 025import org.jetbrains.jet.lang.diagnostics.Errors; 026import org.jetbrains.jet.lang.psi.*; 027import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 028import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; 029import org.jetbrains.jet.lang.resolve.calls.CallResolver; 030import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; 031import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; 032import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; 033import org.jetbrains.jet.lang.resolve.constants.*; 034import org.jetbrains.jet.lang.resolve.scopes.JetScope; 035import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; 036import org.jetbrains.jet.lang.types.ErrorUtils; 037import org.jetbrains.jet.lang.types.JetType; 038import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; 039import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 040 041import javax.inject.Inject; 042import java.util.Collections; 043import java.util.List; 044import java.util.Map; 045 046import static org.jetbrains.jet.lang.resolve.BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT; 047import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; 048 049public 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}