| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.codehaus.groovy.control; |
| |
| import org.codehaus.groovy.ast.ClassCodeVisitorSupport; |
| import org.codehaus.groovy.ast.ClassHelper; |
| import org.codehaus.groovy.ast.ClassNode; |
| import org.codehaus.groovy.ast.MethodNode; |
| import org.codehaus.groovy.ast.expr.CastExpression; |
| import org.codehaus.groovy.ast.expr.ConstantExpression; |
| import org.codehaus.groovy.ast.expr.Expression; |
| import org.codehaus.groovy.ast.stmt.ExpressionStatement; |
| import org.codehaus.groovy.ast.stmt.ReturnStatement; |
| import org.codehaus.groovy.ast.stmt.Statement; |
| import org.codehaus.groovy.classgen.Verifier; |
| |
| import java.math.BigDecimal; |
| |
| import static org.apache.groovy.ast.tools.ExpressionUtils.transformInlineConstants; |
| |
| /** |
| * Visitor to resolve constants in annotation definitions. |
| */ |
| public class AnnotationConstantsVisitor extends ClassCodeVisitorSupport { |
| private SourceUnit source; |
| private boolean inAnnotationDef; |
| |
| public void visitClass(ClassNode node, SourceUnit source) { |
| this.source = source; |
| this.inAnnotationDef = node.isAnnotationDefinition(); |
| super.visitClass(node); |
| this.inAnnotationDef = false; |
| } |
| |
| @Override |
| protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) { |
| if (!inAnnotationDef) return; |
| visitStatement(node.getFirstStatement(), node.getReturnType()); |
| } |
| |
| private static void visitStatement(Statement statement, ClassNode returnType) { |
| if (statement instanceof ReturnStatement) { |
| // normal path |
| ReturnStatement rs = (ReturnStatement) statement; |
| rs.setExpression(transformConstantExpression(rs.getExpression(), returnType)); |
| } else if (statement instanceof ExpressionStatement) { |
| // path for JavaStubGenerator |
| ExpressionStatement es = (ExpressionStatement) statement; |
| es.setExpression(transformConstantExpression(es.getExpression(), returnType)); |
| } |
| } |
| |
| private static Expression transformConstantExpression(Expression val, ClassNode returnType) { |
| ClassNode returnWrapperType = ClassHelper.getWrapper(returnType); |
| if (val instanceof ConstantExpression) { |
| Expression result = revertType(val, returnWrapperType); |
| if (result != null) { |
| return result; |
| } |
| return val; |
| } |
| if (val instanceof CastExpression) { |
| CastExpression castExp = (CastExpression) val; |
| Expression castee = castExp.getExpression(); |
| if (castee instanceof ConstantExpression) { |
| if (ClassHelper.getWrapper(castee.getType()).isDerivedFrom(returnWrapperType)) { |
| return castee; |
| } |
| Expression result = revertType(castee, returnWrapperType); |
| if (result != null) { |
| return result; |
| } |
| return castee; |
| } |
| } |
| return transformInlineConstants(val, returnType); |
| } |
| |
| private static Expression revertType(Expression val, ClassNode returnWrapperType) { |
| ConstantExpression ce = (ConstantExpression) val; |
| if (ClassHelper.Character_TYPE.equals(returnWrapperType) && ClassHelper.STRING_TYPE.equals(val.getType())) { |
| return configure(val, Verifier.transformToPrimitiveConstantIfPossible((ConstantExpression) val)); |
| } |
| ClassNode valWrapperType = ClassHelper.getWrapper(val.getType()); |
| if (ClassHelper.Integer_TYPE.equals(valWrapperType)) { |
| Integer i = (Integer) ce.getValue(); |
| if (ClassHelper.Character_TYPE.equals(returnWrapperType)) { |
| return configure(val, new ConstantExpression((char) i.intValue(), true)); |
| } |
| if (ClassHelper.Short_TYPE.equals(returnWrapperType)) { |
| return configure(val, new ConstantExpression(i.shortValue(), true)); |
| } |
| if (ClassHelper.Byte_TYPE.equals(returnWrapperType)) { |
| return configure(val, new ConstantExpression(i.byteValue(), true)); |
| } |
| } |
| if (ClassHelper.BigDecimal_TYPE.equals(valWrapperType)) { |
| BigDecimal bd = (BigDecimal) ce.getValue(); |
| if (ClassHelper.Float_TYPE.equals(returnWrapperType)) { |
| return configure(val, new ConstantExpression(bd.floatValue(), true)); |
| } |
| if (ClassHelper.Double_TYPE.equals(returnWrapperType)) { |
| return configure(val, new ConstantExpression(bd.doubleValue(), true)); |
| } |
| } |
| return null; |
| } |
| |
| private static Expression configure(Expression orig, Expression result) { |
| result.setSourcePosition(orig); |
| return result; |
| } |
| |
| protected SourceUnit getSourceUnit() { |
| return source; |
| } |
| } |