use of org.codehaus.groovy.ast.expr.DeclarationExpression in project grails-core by grails.
the class ControllerActionTransformer method initializeAndValidateCommandObjectParameter.
protected void initializeAndValidateCommandObjectParameter(final BlockStatement wrapper, final ClassNode controllerNode, final ClassNode commandObjectNode, final ASTNode actionNode, final String actionName, final String paramName, final SourceUnit source, final GeneratorContext context) {
final DeclarationExpression declareCoExpression = new DeclarationExpression(new VariableExpression(paramName, commandObjectNode), Token.newSymbol(Types.EQUALS, 0, 0), new EmptyExpression());
wrapper.addStatement(new ExpressionStatement(declareCoExpression));
if (commandObjectNode.isInterface() || Modifier.isAbstract(commandObjectNode.getModifiers())) {
final String warningMessage = "The [" + actionName + "] action in [" + controllerNode.getName() + "] accepts a parameter of type [" + commandObjectNode.getName() + "]. Interface types and abstract class types are not supported as command objects. This parameter will be ignored.";
GrailsASTUtils.warning(source, actionNode, warningMessage);
} else {
initializeCommandObjectParameter(wrapper, commandObjectNode, paramName, source);
@SuppressWarnings("unchecked") boolean argumentIsValidateable = GrailsASTUtils.hasAnyAnnotations(commandObjectNode, grails.persistence.Entity.class, javax.persistence.Entity.class) || commandObjectNode.implementsInterface(ClassHelper.make(Validateable.class));
if (!argumentIsValidateable && commandObjectNode.isPrimaryClassNode()) {
final ModuleNode commandObjectModule = commandObjectNode.getModule();
if (commandObjectModule != null && this.compilationUnit != null) {
if (commandObjectModule == controllerNode.getModule() || doesModulePathIncludeSubstring(commandObjectModule, "grails-app" + File.separator + "controllers" + File.separator)) {
TraitInjectionUtils.injectTrait(compilationUnit, source, commandObjectNode, Validateable.class);
List<ConstructorNode> declaredConstructors = commandObjectNode.getDeclaredConstructors();
List<Statement> objectInitializerStatements = commandObjectNode.getObjectInitializerStatements();
if (declaredConstructors.isEmpty() && !objectInitializerStatements.isEmpty()) {
BlockStatement constructorLogic = new BlockStatement();
ConstructorNode constructorNode = new ConstructorNode(Modifier.PUBLIC, constructorLogic);
commandObjectNode.addConstructor(constructorNode);
constructorLogic.addStatements(objectInitializerStatements);
}
argumentIsValidateable = true;
} else if (doesModulePathIncludeSubstring(commandObjectModule, "grails-app" + File.separator + "domain" + File.separator)) {
argumentIsValidateable = true;
}
}
}
if (argumentIsValidateable) {
final MethodCallExpression validateMethodCallExpression = new MethodCallExpression(new VariableExpression(paramName), "validate", EMPTY_TUPLE);
final MethodNode validateMethod = commandObjectNode.getMethod("validate", new Parameter[0]);
if (validateMethod != null) {
validateMethodCallExpression.setMethodTarget(validateMethod);
}
final Statement ifCommandObjectIsNotNullThenValidate = new IfStatement(new BooleanExpression(new VariableExpression(paramName)), new ExpressionStatement(validateMethodCallExpression), new ExpressionStatement(new EmptyExpression()));
wrapper.addStatement(ifCommandObjectIsNotNullThenValidate);
} else {
// try to dynamically invoke the .validate() method if it is available at runtime...
final Expression respondsToValidateMethodCallExpression = new MethodCallExpression(new VariableExpression(paramName), "respondsTo", new ArgumentListExpression(new ConstantExpression("validate")));
final Expression validateMethodCallExpression = new MethodCallExpression(new VariableExpression(paramName), "validate", new ArgumentListExpression());
final Statement ifRespondsToValidateThenValidateStatement = new IfStatement(new BooleanExpression(respondsToValidateMethodCallExpression), new ExpressionStatement(validateMethodCallExpression), new ExpressionStatement(new EmptyExpression()));
final Statement ifCommandObjectIsNotNullThenValidate = new IfStatement(new BooleanExpression(new VariableExpression(paramName)), ifRespondsToValidateThenValidateStatement, new ExpressionStatement(new EmptyExpression()));
wrapper.addStatement(ifCommandObjectIsNotNullThenValidate);
final String warningMessage = "The [" + actionName + "] action accepts a parameter of type [" + commandObjectNode.getName() + "] which does not implement grails.validation.Validateable. Data binding will still be applied " + "to this command object but the instance will not be validateable.";
GrailsASTUtils.warning(source, actionNode, warningMessage);
}
if (GrailsASTUtils.isInnerClassNode(commandObjectNode)) {
final String warningMessage = "The [" + actionName + "] action accepts a parameter of type [" + commandObjectNode.getName() + "] which is an inner class. Command object classes should not be inner classes.";
GrailsASTUtils.warning(source, actionNode, warningMessage);
} else {
new DefaultASTDatabindingHelper().injectDatabindingCode(source, context, commandObjectNode);
}
}
}
use of org.codehaus.groovy.ast.expr.DeclarationExpression in project grails-core by grails.
the class ControllerActionTransformer method initializePrimitiveOrTypeWrapperParameter.
protected void initializePrimitiveOrTypeWrapperParameter(final ClassNode classNode, final BlockStatement wrapper, final Parameter param, final String requestParameterName) {
final ClassNode paramTypeClassNode = param.getType();
final String methodParamName = param.getName();
final Expression defaultValueExpression;
if (paramTypeClassNode.equals(ClassHelper.Boolean_TYPE)) {
defaultValueExpression = new ConstantExpression(false);
} else if (PRIMITIVE_CLASS_NODES.contains(paramTypeClassNode)) {
defaultValueExpression = new ConstantExpression(0);
} else {
defaultValueExpression = new ConstantExpression(null);
}
final ConstantExpression paramConstantExpression = new ConstantExpression(requestParameterName);
final Expression paramsTypeConversionMethodArguments = new ArgumentListExpression(paramConstantExpression, /*, defaultValueExpression*/
new ConstantExpression(null));
final String conversionMethodName;
if (TYPE_WRAPPER_CLASS_TO_CONVERSION_METHOD_NAME.containsKey(paramTypeClassNode)) {
conversionMethodName = TYPE_WRAPPER_CLASS_TO_CONVERSION_METHOD_NAME.get(paramTypeClassNode);
} else {
conversionMethodName = paramTypeClassNode.getName();
}
Expression getParamsExpression = buildGetPropertyExpression(new VariableExpression("this"), "params", classNode);
final MethodCallExpression retrieveConvertedValueExpression = new MethodCallExpression(getParamsExpression, conversionMethodName, paramsTypeConversionMethodArguments);
// choose any
Class<?> defaultValueClass = null;
if ("char".equals(conversionMethodName)) {
// TypeConvertingMap.'char' method has 2 different signatures, choose the one with "Character 'char'(String name, Integer defaultValue)" signature
defaultValueClass = Integer.class;
}
applyMethodTarget(retrieveConvertedValueExpression, TypeConvertingMap.class, null, defaultValueClass);
final Expression paramsContainsKeyMethodArguments = new ArgumentListExpression(paramConstantExpression);
final BooleanExpression containsKeyExpression = new BooleanExpression(applyDefaultMethodTarget(new MethodCallExpression(getParamsExpression, "containsKey", paramsContainsKeyMethodArguments), Map.class));
final Token equalsToken = Token.newSymbol(Types.EQUALS, 0, 0);
final VariableExpression convertedValueExpression = new VariableExpression("___converted_" + methodParamName, new ClassNode(Object.class));
final DeclarationExpression declareConvertedValueExpression = new DeclarationExpression(convertedValueExpression, equalsToken, new EmptyExpression());
Statement declareVariableStatement = new ExpressionStatement(declareConvertedValueExpression);
wrapper.addStatement(declareVariableStatement);
final VariableExpression methodParamExpression = new VariableExpression(methodParamName, paramTypeClassNode);
final DeclarationExpression declareParameterVariableStatement = new DeclarationExpression(methodParamExpression, equalsToken, new EmptyExpression());
declareVariableStatement = new ExpressionStatement(declareParameterVariableStatement);
wrapper.addStatement(declareVariableStatement);
final Expression assignmentExpression = new BinaryExpression(convertedValueExpression, equalsToken, new TernaryExpression(containsKeyExpression, retrieveConvertedValueExpression, defaultValueExpression));
wrapper.addStatement(new ExpressionStatement(assignmentExpression));
Expression rejectValueMethodCallExpression = getRejectValueExpression(classNode, methodParamName);
BlockStatement ifConvertedValueIsNullBlockStatement = new BlockStatement();
ifConvertedValueIsNullBlockStatement.addStatement(new ExpressionStatement(rejectValueMethodCallExpression));
ifConvertedValueIsNullBlockStatement.addStatement(new ExpressionStatement(new BinaryExpression(methodParamExpression, equalsToken, defaultValueExpression)));
final BooleanExpression isConvertedValueNullExpression = new BooleanExpression(new BinaryExpression(convertedValueExpression, Token.newSymbol(Types.COMPARE_EQUAL, 0, 0), new ConstantExpression(null)));
final ExpressionStatement assignConvertedValueToParamStatement = new ExpressionStatement(new BinaryExpression(methodParamExpression, equalsToken, convertedValueExpression));
final Statement ifStatement = new IfStatement(isConvertedValueNullExpression, ifConvertedValueIsNullBlockStatement, assignConvertedValueToParamStatement);
wrapper.addStatement(new IfStatement(new BooleanExpression(containsKeyExpression), ifStatement, new ExpressionStatement(new EmptyExpression())));
}
use of org.codehaus.groovy.ast.expr.DeclarationExpression in project grails-core by grails.
the class DefaultASTValidateableHelper method addGetConstraintsMethod.
protected void addGetConstraintsMethod(final ClassNode classNode, boolean defaultNullable) {
final String getConstraintsMethodName = "getConstraints";
MethodNode getConstraintsMethod = classNode.getMethod(getConstraintsMethodName, ZERO_PARAMETERS);
if (getConstraintsMethod == null || !getConstraintsMethod.getDeclaringClass().equals(classNode)) {
final BooleanExpression isConstraintsPropertyNull = new BooleanExpression(new BinaryExpression(new VariableExpression(CONSTRAINED_PROPERTIES_PROPERTY_NAME), Token.newSymbol(Types.COMPARE_EQUAL, 0, 0), new ConstantExpression(null)));
final BlockStatement ifConstraintsPropertyIsNullBlockStatement = new BlockStatement();
final ArgumentListExpression getConstrainedPropertiesForClassArguments = new ArgumentListExpression();
getConstrainedPropertiesForClassArguments.addExpression(new VariableExpression("this"));
getConstrainedPropertiesForClassArguments.addExpression(new ConstantExpression(defaultNullable));
final Expression getConstraintsMethodCall = new StaticMethodCallExpression(ClassHelper.make(ValidationSupport.class), "getConstrainedPropertiesForClass", getConstrainedPropertiesForClassArguments);
final Expression initializeConstraintsFieldExpression = new BinaryExpression(new VariableExpression(CONSTRAINED_PROPERTIES_PROPERTY_NAME), Token.newSymbol(Types.EQUALS, 0, 0), getConstraintsMethodCall);
final Statement ifConstraintsPropertyIsNullStatement = new IfStatement(isConstraintsPropertyNull, ifConstraintsPropertyIsNullBlockStatement, new ExpressionStatement(new EmptyExpression()));
ifConstraintsPropertyIsNullBlockStatement.addStatement(new ExpressionStatement(initializeConstraintsFieldExpression));
if (!defaultNullable) {
final Map<String, ClassNode> propertiesToConstrain = getPropertiesToEnsureConstraintsFor(classNode);
for (final Map.Entry<String, ClassNode> entry : propertiesToConstrain.entrySet()) {
final String propertyName = entry.getKey();
final ClassNode propertyType = entry.getValue();
final String cpName = "$" + propertyName + "$constrainedProperty";
final ArgumentListExpression constrainedPropertyConstructorArgumentList = new ArgumentListExpression();
constrainedPropertyConstructorArgumentList.addExpression(new ClassExpression(classNode));
constrainedPropertyConstructorArgumentList.addExpression(new ConstantExpression(propertyName));
constrainedPropertyConstructorArgumentList.addExpression(new ClassExpression(propertyType));
final ConstructorCallExpression constrainedPropertyCtorCallExpression = new ConstructorCallExpression(new ClassNode(ConstrainedProperty.class), constrainedPropertyConstructorArgumentList);
final Expression declareConstrainedPropertyExpression = new DeclarationExpression(new VariableExpression(cpName, ClassHelper.OBJECT_TYPE), Token.newSymbol(Types.EQUALS, 0, 0), constrainedPropertyCtorCallExpression);
final ArgumentListExpression applyConstraintMethodArgumentList = new ArgumentListExpression();
applyConstraintMethodArgumentList.addExpression(new ConstantExpression(ConstrainedProperty.NULLABLE_CONSTRAINT));
applyConstraintMethodArgumentList.addExpression(new ConstantExpression(defaultNullable));
final Expression applyNullableConstraintMethodCallExpression = new MethodCallExpression(new VariableExpression(cpName), "applyConstraint", applyConstraintMethodArgumentList);
final ArgumentListExpression putMethodArgumentList = new ArgumentListExpression();
putMethodArgumentList.addExpression(new ConstantExpression(propertyName));
putMethodArgumentList.addExpression(new VariableExpression(cpName));
final MethodCallExpression addToConstraintsMapExpression = new MethodCallExpression(new VariableExpression(CONSTRAINED_PROPERTIES_PROPERTY_NAME), "put", putMethodArgumentList);
final BlockStatement addNullableConstraintBlock = new BlockStatement();
addNullableConstraintBlock.addStatement(new ExpressionStatement(declareConstrainedPropertyExpression));
addNullableConstraintBlock.addStatement(new ExpressionStatement(applyNullableConstraintMethodCallExpression));
addNullableConstraintBlock.addStatement(new ExpressionStatement(addToConstraintsMapExpression));
final Expression constraintsMapContainsKeyExpression = new MethodCallExpression(new VariableExpression(CONSTRAINED_PROPERTIES_PROPERTY_NAME, ClassHelper.make(Map.class)), "containsKey", new ArgumentListExpression(new ConstantExpression(propertyName)));
final BooleanExpression ifPropertyIsAlreadyConstrainedExpression = new BooleanExpression(constraintsMapContainsKeyExpression);
final Statement ifPropertyIsAlreadyConstrainedStatement = new IfStatement(ifPropertyIsAlreadyConstrainedExpression, new ExpressionStatement(new EmptyExpression()), addNullableConstraintBlock);
ifConstraintsPropertyIsNullBlockStatement.addStatement(ifPropertyIsAlreadyConstrainedStatement);
}
}
final BlockStatement methodBlockStatement = new BlockStatement();
methodBlockStatement.addStatement(ifConstraintsPropertyIsNullStatement);
final Statement returnStatement = new ReturnStatement(new VariableExpression(CONSTRAINED_PROPERTIES_PROPERTY_NAME));
methodBlockStatement.addStatement(returnStatement);
final MethodNode methodNode = new MethodNode(getConstraintsMethodName, Modifier.STATIC | Modifier.PUBLIC, new ClassNode(Map.class), ZERO_PARAMETERS, null, methodBlockStatement);
if (classNode.redirect() == null) {
classNode.addMethod(methodNode);
} else {
classNode.redirect().addMethod(methodNode);
}
}
}
use of org.codehaus.groovy.ast.expr.DeclarationExpression in project groovy-core by groovy.
the class BaseScriptASTTransformation method visit.
public void visit(ASTNode[] nodes, SourceUnit source) {
init(nodes, source);
AnnotatedNode parent = (AnnotatedNode) nodes[1];
AnnotationNode node = (AnnotationNode) nodes[0];
if (!MY_TYPE.equals(node.getClassNode()))
return;
if (parent instanceof DeclarationExpression) {
changeBaseScriptTypeFromDeclaration((DeclarationExpression) parent, node);
} else if (parent instanceof ImportNode || parent instanceof PackageNode) {
changeBaseScriptTypeFromPackageOrImport(source, parent, node);
} else if (parent instanceof ClassNode) {
changeBaseScriptTypeFromClass((ClassNode) parent, node);
}
}
use of org.codehaus.groovy.ast.expr.DeclarationExpression in project groovy-core by groovy.
the class FieldASTTransformation method visit.
public void visit(ASTNode[] nodes, SourceUnit source) {
sourceUnit = source;
if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
throw new GroovyBugError("Internal error: expecting [AnnotationNode, AnnotatedNode] but got: " + Arrays.asList(nodes));
}
AnnotatedNode parent = (AnnotatedNode) nodes[1];
AnnotationNode node = (AnnotationNode) nodes[0];
if (!MY_TYPE.equals(node.getClassNode()))
return;
if (parent instanceof DeclarationExpression) {
DeclarationExpression de = (DeclarationExpression) parent;
ClassNode cNode = de.getDeclaringClass();
if (!cNode.isScript()) {
addError("Annotation " + MY_TYPE_NAME + " can only be used within a Script.", parent);
return;
}
candidate = de;
// GROOVY-4548: temp fix to stop CCE until proper support is added
if (de.isMultipleAssignmentDeclaration()) {
addError("Annotation " + MY_TYPE_NAME + " not supported with multiple assignment notation.", parent);
return;
}
VariableExpression ve = de.getVariableExpression();
variableName = ve.getName();
// set owner null here, it will be updated by addField
fieldNode = new FieldNode(variableName, ve.getModifiers(), ve.getType(), null, de.getRightExpression());
fieldNode.setSourcePosition(de);
cNode.addField(fieldNode);
// GROOVY-4833 : annotations that are not Groovy transforms should be transferred to the generated field
// GROOVY-6112 : also copy acceptable Groovy transforms
final List<AnnotationNode> annotations = de.getAnnotations();
for (AnnotationNode annotation : annotations) {
// GROOVY-6337 HACK: in case newly created field is @Lazy
if (annotation.getClassNode().equals(LAZY_TYPE)) {
LazyASTTransformation.visitField(annotation, fieldNode);
}
final ClassNode annotationClassNode = annotation.getClassNode();
if (notTransform(annotationClassNode) || acceptableTransform(annotation)) {
fieldNode.addAnnotation(annotation);
}
}
super.visitClass(cNode);
// GROOVY-5207 So that Closures can see newly added fields
// (not super efficient for a very large class with many @Fields but we chose simplicity
// and understandability of this solution over more complex but efficient alternatives)
VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(source);
scopeVisitor.visitClass(cNode);
}
}
Aggregations