diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index 95c6e083d49..2d9d8507322 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -47,7 +47,6 @@ import java.util.Map; import static org.jetbrains.jet.lang.resolve.BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT; import static org.jetbrains.jet.lang.resolve.BindingContext.COMPILE_TIME_INITIALIZER; -import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumEntry; import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; public class AnnotationResolver { @@ -206,7 +205,7 @@ public class AnnotationResolver { } } - private void resolveAnnotationArgument( + public static void resolveAnnotationArgument( @NotNull AnnotationDescriptorImpl annotationDescriptor, @NotNull ResolvedCall call, @NotNull BindingTrace trace @@ -233,7 +232,7 @@ public class AnnotationResolver { } @NotNull - private List> resolveValueArguments( + private static List> resolveValueArguments( @NotNull ResolvedValueArgument resolvedValueArgument, @NotNull JetType expectedType, @NotNull BindingTrace trace @@ -252,115 +251,20 @@ public class AnnotationResolver { } @Nullable - public CompileTimeConstant resolveExpressionToCompileTimeValue( + public static CompileTimeConstant resolveExpressionToCompileTimeValue( @NotNull JetExpression expression, - @NotNull final JetType expectedType, - @NotNull final BindingTrace trace + @NotNull JetType expectedType, + @NotNull BindingTrace trace ) { - JetVisitor, Void> visitor = new JetVisitor, Void>() { - @Override - public CompileTimeConstant visitConstantExpression(@NotNull JetConstantExpression expression, Void nothing) { - JetType type = expressionTypingServices.getType(JetScope.EMPTY, expression, expectedType, DataFlowInfo.EMPTY, trace); - if (type == null) { - // TODO: - // trace.report(ANNOTATION_PARAMETER_SHOULD_BE_CONSTANT.on(expression)); - } - return trace.get(BindingContext.COMPILE_TIME_VALUE, expression); - } + return expression.accept(new ConstantExpressionEvaluator(trace, expectedType), null); + } - - // @Override -// public CompileTimeConstant visitAnnotation(JetAnnotation annotation, Void nothing) { -// super.visitAnnotation(annotation, null); // TODO -// } -// -// @Override -// public CompileTimeConstant visitAnnotationEntry(JetAnnotationEntry annotationEntry, Void nothing) { -// return super.visitAnnotationEntry(annotationEntry, null); // TODO -// } - - @Override - public CompileTimeConstant visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, Void nothing) { - JetExpression innerExpression = expression.getExpression(); - if (innerExpression == null) return null; - return innerExpression.accept(this, null); - } - - @Override - public CompileTimeConstant visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, Void nothing) { - return trace.get(BindingContext.COMPILE_TIME_VALUE, expression); - } - - @Override - public CompileTimeConstant visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, Void data) { - DeclarationDescriptor descriptor = trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, expression); - if (descriptor != null && isEnumEntry(descriptor)) { - return new EnumValue((ClassDescriptor) descriptor); - } - - ResolvedCall resolvedCall = trace.getBindingContext().get(BindingContext.RESOLVED_CALL, expression); - if (resolvedCall != null) { - CallableDescriptor callableDescriptor = resolvedCall.getResultingDescriptor(); - if (callableDescriptor instanceof PropertyDescriptor) { - PropertyDescriptor propertyDescriptor = (PropertyDescriptor) callableDescriptor; - if (AnnotationUtils.isPropertyAcceptableAsAnnotationParameter(propertyDescriptor)) { - return trace.getBindingContext().get(COMPILE_TIME_INITIALIZER, propertyDescriptor); - } - } - } - return null; - } - - @Override - public CompileTimeConstant visitQualifiedExpression(@NotNull JetQualifiedExpression expression, Void data) { - JetExpression selectorExpression = expression.getSelectorExpression(); - if (selectorExpression != null) { - return selectorExpression.accept(this, null); - } - return super.visitQualifiedExpression(expression, data); - } - - @Override - public CompileTimeConstant visitCallExpression(@NotNull JetCallExpression expression, Void data) { - ResolvedCall call = - trace.getBindingContext().get(BindingContext.RESOLVED_CALL, (expression).getCalleeExpression()); - if (call != null) { - CallableDescriptor resultingDescriptor = call.getResultingDescriptor(); - if (AnnotationUtils.isArrayMethodCall(call)) { - JetType type = resultingDescriptor.getValueParameters().iterator().next().getVarargElementType(); - List> arguments = Lists.newArrayList(); - for (ResolvedValueArgument descriptorToArgument : call.getValueArguments().values()) { - arguments.addAll(resolveValueArguments(descriptorToArgument, type, trace)); - } - return new ArrayValue(arguments, resultingDescriptor.getReturnType()); - } - - if (resultingDescriptor instanceof ConstructorDescriptor) { - JetType constructorReturnType = resultingDescriptor.getReturnType(); - assert constructorReturnType != null : "Constructor should have return type"; - if (DescriptorUtils.isAnnotationClass(constructorReturnType.getConstructor().getDeclarationDescriptor())) { - AnnotationDescriptorImpl descriptor = new AnnotationDescriptorImpl(); - descriptor.setAnnotationType(constructorReturnType); - resolveAnnotationArgument(descriptor, call, trace); - return new AnnotationValue(descriptor); - } - } - - if (AnnotationUtils.isJavaClassMethodCall(call)) { - return new JavaClassValue(resultingDescriptor.getReturnType()); - } - } - return null; - } - - @Override - public CompileTimeConstant visitJetElement(@NotNull JetElement element, Void nothing) { - // TODO: - //trace.report(ANNOTATION_PARAMETER_SHOULD_BE_CONSTANT.on(element)); - return null; - } - }; - return expression.accept(visitor, null); + @NotNull + public List getResolvedAnnotations(@Nullable JetModifierList modifierList, BindingTrace trace) { + if (modifierList == null) { + return Collections.emptyList(); + } + return getResolvedAnnotations(modifierList.getAnnotationEntries(), trace); } @SuppressWarnings("MethodMayBeStatic") diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 14507de3660..9cda2dcbb0a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -556,7 +556,7 @@ public class BodyResolver { JetType expectedTypeForInitializer = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE; expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, context.getOuterDataFlowInfo(), trace); if (AnnotationUtils.isPropertyAcceptableAsAnnotationParameter(propertyDescriptor)) { - CompileTimeConstant constant = annotationResolver.resolveExpressionToCompileTimeValue(initializer, expectedTypeForInitializer, trace); + CompileTimeConstant constant = AnnotationResolver.resolveExpressionToCompileTimeValue(initializer, expectedTypeForInitializer, trace); if (constant != null) { trace.record(BindingContext.COMPILE_TIME_INITIALIZER, propertyDescriptor, constant); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ConstantExpressionEvaluator.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ConstantExpressionEvaluator.java new file mode 100644 index 00000000000..ada0b5ab2b8 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ConstantExpressionEvaluator.java @@ -0,0 +1,144 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve; + +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptorImpl; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; +import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; +import org.jetbrains.jet.lang.resolve.constants.*; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.types.JetType; + +import javax.rmi.CORBA.ClassDesc; +import java.util.List; + +import static org.jetbrains.jet.lang.resolve.BindingContext.COMPILE_TIME_INITIALIZER; + +public class ConstantExpressionEvaluator extends JetVisitor, Void> { + @NotNull private final BindingTrace trace; + @NotNull private final JetType expectedType; + + public ConstantExpressionEvaluator(@NotNull BindingTrace trace, @NotNull JetType expectedType) { + this.trace = trace; + this.expectedType = expectedType; + } + + @Override + public CompileTimeConstant visitConstantExpression(@NotNull JetConstantExpression expression, Void nothing) { + return trace.get(BindingContext.COMPILE_TIME_VALUE, expression); + } + + @Override + public CompileTimeConstant visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, Void nothing) { + JetExpression innerExpression = expression.getExpression(); + if (innerExpression == null) return null; + return innerExpression.accept(this, null); + } + + @Override + public CompileTimeConstant visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, Void nothing) { + return trace.get(BindingContext.COMPILE_TIME_VALUE, expression); + } + + @Override + public CompileTimeConstant visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, Void data) { + DeclarationDescriptor descriptor = trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, expression); + if (descriptor != null && DescriptorUtils.isEnumEntry(descriptor)) { + return new EnumValue((ClassDescriptor) descriptor); + } + + ResolvedCall resolvedCall = + trace.getBindingContext().get(BindingContext.RESOLVED_CALL, expression); + if (resolvedCall != null) { + CallableDescriptor callableDescriptor = resolvedCall.getResultingDescriptor(); + if (callableDescriptor instanceof PropertyDescriptor) { + PropertyDescriptor propertyDescriptor = (PropertyDescriptor) callableDescriptor; + if (AnnotationUtils.isPropertyAcceptableAsAnnotationParameter(propertyDescriptor)) { + return trace.getBindingContext().get(COMPILE_TIME_INITIALIZER, propertyDescriptor); + } + } + } + + return null; + } + + @Override + public CompileTimeConstant visitQualifiedExpression(@NotNull JetQualifiedExpression expression, Void data) { + JetExpression selectorExpression = expression.getSelectorExpression(); + if (selectorExpression != null) { + return selectorExpression.accept(this, null); + } + return super.visitQualifiedExpression(expression, data); + } + + @Override + public CompileTimeConstant visitCallExpression(@NotNull JetCallExpression expression, Void data) { + ResolvedCall call = + trace.getBindingContext().get(BindingContext.RESOLVED_CALL, (expression).getCalleeExpression()); + if (call != null) { + CallableDescriptor resultingDescriptor = call.getResultingDescriptor(); + if (AnnotationUtils.isArrayMethodCall(call)) { + JetType type = resultingDescriptor.getValueParameters().iterator().next().getVarargElementType(); + List> arguments = Lists.newArrayList(); + for (ResolvedValueArgument descriptorToArgument : call.getValueArguments().values()) { + arguments.addAll(resolveArguments(descriptorToArgument.getArguments(), type, trace)); + } + return new ArrayValue(arguments, resultingDescriptor.getReturnType()); + } + + if (resultingDescriptor instanceof ConstructorDescriptor) { + JetType constructorReturnType = resultingDescriptor.getReturnType(); + assert constructorReturnType != null : "Constructor should have return type"; + if (DescriptorUtils.isAnnotationClass(constructorReturnType.getConstructor().getDeclarationDescriptor())) { + AnnotationDescriptorImpl descriptor = new AnnotationDescriptorImpl(); + descriptor.setAnnotationType(constructorReturnType); + AnnotationResolver.resolveAnnotationArgument(descriptor, call, trace); + return new AnnotationValue(descriptor); + } + } + + if (AnnotationUtils.isJavaClassMethodCall(call)) { + return new JavaClassValue(resultingDescriptor.getReturnType()); + } + } + return null; + } + + @NotNull + private static List> resolveArguments(@NotNull List valueArguments, @NotNull JetType expectedType, @NotNull BindingTrace trace) { + List> constants = Lists.newArrayList(); + for (ValueArgument argument : valueArguments) { + JetExpression argumentExpression = argument.getArgumentExpression(); + if (argumentExpression != null) { + CompileTimeConstant constant = argumentExpression.accept(new ConstantExpressionEvaluator(trace, expectedType), null); + if (constant != null) { + constants.add(constant); + } + } + } + return constants; + } + + @Override + public CompileTimeConstant visitJetElement(@NotNull JetElement element, Void nothing) { + return null; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java index 175525625a5..c29fb6bddee 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java @@ -396,7 +396,7 @@ public class ExpressionTypingServices { getType(declaringScope, defaultValue, valueParameterDescriptor.getType(), dataFlowInfo, trace); if (DescriptorUtils.isAnnotationClass(DescriptorUtils.getContainingClass(declaringScope))) { CompileTimeConstant constant = - annotationResolver.resolveExpressionToCompileTimeValue(defaultValue, valueParameterDescriptor.getType(), trace); + AnnotationResolver.resolveExpressionToCompileTimeValue(defaultValue, valueParameterDescriptor.getType(), trace); if (constant != null) { trace.record(BindingContext.COMPILE_TIME_VALUE, defaultValue, constant); }