use of org.codehaus.groovy.ast.Parameter in project grails-core by grails.
the class DefaultASTDatabindingHelper method getPropertyNamesToIncludeInWhiteList.
private Set<String> getPropertyNamesToIncludeInWhiteList(final SourceUnit sourceUnit, final ClassNode classNode) {
final Set<String> propertyNamesToIncludeInWhiteList = new HashSet<String>();
final Set<String> unbindablePropertyNames = new HashSet<String>();
final Set<String> bindablePropertyNames = new HashSet<String>();
if (!classNode.getSuperClass().equals(new ClassNode(Object.class))) {
final Set<String> parentClassPropertyNames = getPropertyNamesToIncludeInWhiteListForParentClass(sourceUnit, classNode.getSuperClass());
bindablePropertyNames.addAll(parentClassPropertyNames);
}
final FieldNode constraintsFieldNode = classNode.getDeclaredField(CONSTRAINTS_FIELD_NAME);
if (constraintsFieldNode != null && constraintsFieldNode.hasInitialExpression()) {
final Expression constraintsInitialExpression = constraintsFieldNode.getInitialExpression();
if (constraintsInitialExpression instanceof ClosureExpression) {
final Map<String, Map<String, Expression>> constraintsInfo = GrailsASTUtils.getConstraintMetadata((ClosureExpression) constraintsInitialExpression);
for (Entry<String, Map<String, Expression>> constraintConfig : constraintsInfo.entrySet()) {
final String propertyName = constraintConfig.getKey();
final Map<String, Expression> mapEntryExpressions = constraintConfig.getValue();
for (Entry<String, Expression> entry : mapEntryExpressions.entrySet()) {
final String constraintName = entry.getKey();
if (BINDABLE_CONSTRAINT_NAME.equals(constraintName)) {
final Expression valueExpression = entry.getValue();
Boolean bindableValue = null;
if (valueExpression instanceof ConstantExpression) {
final Object constantValue = ((ConstantExpression) valueExpression).getValue();
if (constantValue instanceof Boolean) {
bindableValue = (Boolean) constantValue;
}
}
if (bindableValue != null) {
if (Boolean.TRUE.equals(bindableValue)) {
unbindablePropertyNames.remove(propertyName);
bindablePropertyNames.add(propertyName);
} else {
bindablePropertyNames.remove(propertyName);
unbindablePropertyNames.add(propertyName);
}
} else {
GrailsASTUtils.warning(sourceUnit, valueExpression, "The bindable constraint for property [" + propertyName + "] in class [" + classNode.getName() + "] has a value which is not a boolean literal and will be ignored.");
}
}
}
}
}
}
final Set<String> fieldsInTransientsList = getPropertyNamesExpressedInTransientsList(classNode);
propertyNamesToIncludeInWhiteList.addAll(bindablePropertyNames);
final List<FieldNode> fields = classNode.getFields();
for (FieldNode fieldNode : fields) {
final String fieldName = fieldNode.getName();
final boolean isDomainClass = GrailsASTUtils.isDomainClass(classNode, sourceUnit);
if ((!unbindablePropertyNames.contains(fieldName)) && (bindablePropertyNames.contains(fieldName) || shouldFieldBeInWhiteList(fieldNode, fieldsInTransientsList, isDomainClass))) {
propertyNamesToIncludeInWhiteList.add(fieldName);
}
}
final Map<String, MethodNode> declaredMethodsMap = classNode.getDeclaredMethodsMap();
for (Entry<String, MethodNode> methodEntry : declaredMethodsMap.entrySet()) {
final MethodNode value = methodEntry.getValue();
if (classNode.equals(value.getDeclaringClass())) {
Parameter[] parameters = value.getParameters();
if (parameters != null && parameters.length == 1) {
final String methodName = value.getName();
if (methodName.startsWith("set")) {
final Parameter parameter = parameters[0];
final ClassNode paramType = parameter.getType();
if (!paramType.equals(new ClassNode(Object.class))) {
final String restOfMethodName = methodName.substring(3);
final String propertyName = GrailsNameUtils.getPropertyName(restOfMethodName);
if (!unbindablePropertyNames.contains(propertyName)) {
propertyNamesToIncludeInWhiteList.add(propertyName);
}
}
}
}
}
}
CLASS_NODE_TO_WHITE_LIST_PROPERTY_NAMES.put(classNode, propertyNamesToIncludeInWhiteList);
Map<String, ClassNode> allAssociationMap = GrailsASTUtils.getAllAssociationMap(classNode);
for (String associationName : allAssociationMap.keySet()) {
if (!propertyNamesToIncludeInWhiteList.contains(associationName) && !unbindablePropertyNames.contains(associationName)) {
propertyNamesToIncludeInWhiteList.add(associationName);
}
}
return propertyNamesToIncludeInWhiteList;
}
use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class StaticInvocationWriter method makeCall.
@Override
public void makeCall(final Expression origin, final Expression receiver, final Expression message, final Expression arguments, final MethodCallerMultiAdapter adapter, final boolean safe, final boolean spreadSafe, final boolean implicitThis) {
ClassNode dynamicCallReturnType = origin.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION);
if (dynamicCallReturnType != null) {
StaticTypesWriterController staticController = (StaticTypesWriterController) controller;
if (origin instanceof MethodCallExpression) {
((MethodCallExpression) origin).setMethodTarget(null);
}
InvocationWriter dynamicInvocationWriter = staticController.getRegularInvocationWriter();
dynamicInvocationWriter.makeCall(origin, receiver, message, arguments, adapter, safe, spreadSafe, implicitThis);
return;
}
if (tryImplicitReceiver(origin, message, arguments, adapter, safe, spreadSafe, implicitThis)) {
return;
}
// if call is spread safe, replace it with a for in loop
if (spreadSafe && origin instanceof MethodCallExpression) {
MethodVisitor mv = controller.getMethodVisitor();
CompileStack compileStack = controller.getCompileStack();
TypeChooser typeChooser = controller.getTypeChooser();
OperandStack operandStack = controller.getOperandStack();
ClassNode classNode = controller.getClassNode();
int counter = labelCounter.incrementAndGet();
// create an empty arraylist
VariableExpression result = new VariableExpression("spreadresult" + counter, StaticCompilationVisitor.ARRAYLIST_CLASSNODE);
ConstructorCallExpression cce = new ConstructorCallExpression(StaticCompilationVisitor.ARRAYLIST_CLASSNODE, ArgumentListExpression.EMPTY_ARGUMENTS);
cce.setNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET, StaticCompilationVisitor.ARRAYLIST_CONSTRUCTOR);
DeclarationExpression declr = new DeclarationExpression(result, Token.newSymbol("=", origin.getLineNumber(), origin.getColumnNumber()), cce);
declr.visit(controller.getAcg());
operandStack.pop();
// if (receiver != null)
receiver.visit(controller.getAcg());
Label ifnull = compileStack.createLocalLabel("ifnull_" + counter);
mv.visitJumpInsn(IFNULL, ifnull);
// receiver consumed by if()
operandStack.remove(1);
Label nonull = compileStack.createLocalLabel("nonull_" + counter);
mv.visitLabel(nonull);
ClassNode componentType = StaticTypeCheckingVisitor.inferLoopElementType(typeChooser.resolveType(receiver, classNode));
Parameter iterator = new Parameter(componentType, "for$it$" + counter);
VariableExpression iteratorAsVar = new VariableExpression(iterator);
MethodCallExpression origMCE = (MethodCallExpression) origin;
MethodCallExpression newMCE = new MethodCallExpression(iteratorAsVar, origMCE.getMethodAsString(), origMCE.getArguments());
newMCE.setImplicitThis(false);
newMCE.setMethodTarget(origMCE.getMethodTarget());
newMCE.setSafe(true);
MethodCallExpression add = new MethodCallExpression(result, "add", newMCE);
add.setImplicitThis(false);
add.setMethodTarget(StaticCompilationVisitor.ARRAYLIST_ADD_METHOD);
// for (e in receiver) { result.add(e?.method(arguments) }
ForStatement stmt = new ForStatement(iterator, receiver, new ExpressionStatement(add));
stmt.visit(controller.getAcg());
// else { empty list }
mv.visitLabel(ifnull);
// end of if/else
// return result list
result.visit(controller.getAcg());
} else if (safe && origin instanceof MethodCallExpression) {
// wrap call in an IFNULL check
MethodVisitor mv = controller.getMethodVisitor();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
int counter = labelCounter.incrementAndGet();
// if (receiver != null)
ExpressionAsVariableSlot slot = new ExpressionAsVariableSlot(controller, receiver);
slot.visit(controller.getAcg());
operandStack.box();
Label ifnull = compileStack.createLocalLabel("ifnull_" + counter);
mv.visitJumpInsn(IFNULL, ifnull);
// receiver consumed by if()
operandStack.remove(1);
Label nonull = compileStack.createLocalLabel("nonull_" + counter);
mv.visitLabel(nonull);
MethodCallExpression origMCE = (MethodCallExpression) origin;
MethodCallExpression newMCE = new MethodCallExpression(new VariableSlotLoader(slot.getType(), slot.getIndex(), controller.getOperandStack()), origMCE.getMethodAsString(), origMCE.getArguments());
MethodNode methodTarget = origMCE.getMethodTarget();
newMCE.setMethodTarget(methodTarget);
newMCE.setSafe(false);
newMCE.setImplicitThis(origMCE.isImplicitThis());
newMCE.setSourcePosition(origMCE);
newMCE.visit(controller.getAcg());
compileStack.removeVar(slot.getIndex());
ClassNode returnType = operandStack.getTopOperand();
if (ClassHelper.isPrimitiveType(returnType) && !ClassHelper.VOID_TYPE.equals(returnType)) {
operandStack.box();
}
Label endof = compileStack.createLocalLabel("endof_" + counter);
mv.visitJumpInsn(GOTO, endof);
mv.visitLabel(ifnull);
// else { null }
mv.visitInsn(ACONST_NULL);
mv.visitLabel(endof);
} else {
if ((adapter == AsmClassGenerator.getGroovyObjectField || adapter == AsmClassGenerator.getField) && origin instanceof AttributeExpression) {
String pname = ((PropertyExpression) origin).getPropertyAsString();
CallSiteWriter callSiteWriter = controller.getCallSiteWriter();
if (pname != null && callSiteWriter instanceof StaticTypesCallSiteWriter) {
StaticTypesCallSiteWriter stcsw = (StaticTypesCallSiteWriter) callSiteWriter;
TypeChooser typeChooser = controller.getTypeChooser();
if (stcsw.makeGetField(receiver, typeChooser.resolveType(receiver, controller.getClassNode()), pname, safe, false, true)) {
return;
}
}
}
super.makeCall(origin, receiver, message, arguments, adapter, safe, spreadSafe, implicitThis);
}
}
use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class StaticInvocationWriter method loadArguments.
protected void loadArguments(List<Expression> argumentList, Parameter[] para) {
if (para.length == 0)
return;
ClassNode lastParaType = para[para.length - 1].getOriginType();
AsmClassGenerator acg = controller.getAcg();
TypeChooser typeChooser = controller.getTypeChooser();
OperandStack operandStack = controller.getOperandStack();
ClassNode lastArgType = argumentList.size() > 0 ? typeChooser.resolveType(argumentList.get(argumentList.size() - 1), controller.getClassNode()) : null;
if (lastParaType.isArray() && ((argumentList.size() > para.length) || ((argumentList.size() == (para.length - 1)) && !lastParaType.equals(lastArgType)) || ((argumentList.size() == para.length && lastArgType != null && !lastArgType.isArray()) && (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(lastArgType, lastParaType.getComponentType()))) || ClassHelper.GSTRING_TYPE.equals(lastArgType) && ClassHelper.STRING_TYPE.equals(lastParaType.getComponentType()))) {
int stackLen = operandStack.getStackLength() + argumentList.size();
MethodVisitor mv = controller.getMethodVisitor();
MethodVisitor orig = mv;
//mv = new org.objectweb.asm.util.TraceMethodVisitor(mv);
controller.setMethodVisitor(mv);
// first parameters as usual
for (int i = 0; i < para.length - 1; i++) {
Expression expression = argumentList.get(i);
expression.visit(acg);
if (!isNullConstant(expression)) {
operandStack.doGroovyCast(para[i].getType());
}
}
// last parameters wrapped in an array
List<Expression> lastParams = new LinkedList<Expression>();
for (int i = para.length - 1; i < argumentList.size(); i++) {
lastParams.add(argumentList.get(i));
}
ArrayExpression array = new ArrayExpression(lastParaType.getComponentType(), lastParams);
array.visit(acg);
// adjust stack length
while (operandStack.getStackLength() < stackLen) {
operandStack.push(ClassHelper.OBJECT_TYPE);
}
if (argumentList.size() == para.length - 1) {
operandStack.remove(1);
}
} else if (argumentList.size() == para.length) {
for (int i = 0; i < argumentList.size(); i++) {
Expression expression = argumentList.get(i);
expression.visit(acg);
if (!isNullConstant(expression)) {
operandStack.doGroovyCast(para[i].getType());
}
}
} else {
// method call with default arguments
ClassNode classNode = controller.getClassNode();
Expression[] arguments = new Expression[para.length];
for (int i = 0, j = 0; i < para.length; i++) {
Parameter curParam = para[i];
ClassNode curParamType = curParam.getType();
Expression curArg = j < argumentList.size() ? argumentList.get(j) : null;
Expression initialExpression = (Expression) curParam.getNodeMetaData(StaticTypesMarker.INITIAL_EXPRESSION);
if (initialExpression == null && curParam.hasInitialExpression())
initialExpression = curParam.getInitialExpression();
if (initialExpression == null && curParam.getNodeMetaData(Verifier.INITIAL_EXPRESSION) != null) {
initialExpression = (Expression) curParam.getNodeMetaData(Verifier.INITIAL_EXPRESSION);
}
ClassNode curArgType = curArg == null ? null : typeChooser.resolveType(curArg, classNode);
if (initialExpression != null && !compatibleArgumentType(curArgType, curParamType)) {
// use default expression
arguments[i] = initialExpression;
} else {
arguments[i] = curArg;
j++;
}
}
for (int i = 0; i < arguments.length; i++) {
Expression expression = arguments[i];
expression.visit(acg);
if (!isNullConstant(expression)) {
operandStack.doGroovyCast(para[i].getType());
}
}
}
}
use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class StaticInvocationWriter method writeDirectMethodCall.
@Override
protected boolean writeDirectMethodCall(final MethodNode target, final boolean implicitThis, final Expression receiver, final TupleExpression args) {
if (target == null)
return false;
if (target instanceof ExtensionMethodNode) {
ExtensionMethodNode emn = (ExtensionMethodNode) target;
MethodNode node = emn.getExtensionMethodNode();
String methodName = target.getName();
MethodVisitor mv = controller.getMethodVisitor();
int argumentsToRemove = 0;
List<Expression> argumentList = new LinkedList<Expression>(args.getExpressions());
if (emn.isStaticExtension()) {
// it's a static extension method
argumentList.add(0, ConstantExpression.NULL);
} else {
argumentList.add(0, receiver);
}
Parameter[] parameters = node.getParameters();
loadArguments(argumentList, parameters);
String owner = BytecodeHelper.getClassInternalName(node.getDeclaringClass());
String desc = BytecodeHelper.getMethodDescriptor(target.getReturnType(), parameters);
mv.visitMethodInsn(INVOKESTATIC, owner, methodName, desc, false);
ClassNode ret = target.getReturnType().redirect();
if (ret == ClassHelper.VOID_TYPE) {
ret = ClassHelper.OBJECT_TYPE;
mv.visitInsn(ACONST_NULL);
}
argumentsToRemove += argumentList.size();
controller.getOperandStack().remove(argumentsToRemove);
controller.getOperandStack().push(ret);
return true;
} else {
if (target == StaticTypeCheckingVisitor.CLOSURE_CALL_VARGS) {
// wrap arguments into an array
ArrayExpression arr = new ArrayExpression(ClassHelper.OBJECT_TYPE, args.getExpressions());
return super.writeDirectMethodCall(target, implicitThis, receiver, new ArgumentListExpression(arr));
}
ClassNode classNode = controller.getClassNode();
if (classNode.isDerivedFrom(ClassHelper.CLOSURE_TYPE) && controller.isInClosure() && !target.isPublic() && target.getDeclaringClass() != classNode) {
if (!tryBridgeMethod(target, receiver, implicitThis, args)) {
// replace call with an invoker helper call
ArrayExpression arr = new ArrayExpression(ClassHelper.OBJECT_TYPE, args.getExpressions());
MethodCallExpression mce = new MethodCallExpression(INVOKERHELER_RECEIVER, target.isStatic() ? "invokeStaticMethod" : "invokeMethodSafe", new ArgumentListExpression(target.isStatic() ? new ClassExpression(target.getDeclaringClass()) : receiver, new ConstantExpression(target.getName()), arr));
mce.setMethodTarget(target.isStatic() ? INVOKERHELPER_INVOKESTATICMETHOD : INVOKERHELPER_INVOKEMETHOD);
mce.visit(controller.getAcg());
return true;
}
return true;
}
if (target.isPrivate()) {
if (tryPrivateMethod(target, implicitThis, receiver, args, classNode))
return true;
} else if (target.isProtected()) {
ClassNode node = receiver == null ? ClassHelper.OBJECT_TYPE : controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
boolean isThisOrSuper = false;
if (receiver instanceof VariableExpression) {
isThisOrSuper = ((VariableExpression) receiver).isThisExpression() || ((VariableExpression) receiver).isSuperExpression();
}
if (!implicitThis && !isThisOrSuper && StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(node, target.getDeclaringClass())) {
ASTNode src = receiver == null ? args : receiver;
controller.getSourceUnit().addError(new SyntaxException("Method " + target.getName() + " is protected in " + target.getDeclaringClass().toString(false), src.getLineNumber(), src.getColumnNumber(), src.getLastLineNumber(), src.getLastColumnNumber()));
}
}
if (receiver != null) {
if (!(receiver instanceof VariableExpression) || !((VariableExpression) receiver).isSuperExpression()) {
// in order to avoid calls to castToType, which is the dynamic behaviour, we make sure that we call CHECKCAST instead
// then replace the top operand type
Expression checkCastReceiver = new CheckcastReceiverExpression(receiver, target);
return super.writeDirectMethodCall(target, implicitThis, checkCastReceiver, args);
}
}
return super.writeDirectMethodCall(target, implicitThis, receiver, args);
}
}
use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class StatementWriter method writeTryCatchFinally.
public void writeTryCatchFinally(TryCatchStatement statement) {
controller.getAcg().onLineNumber(statement, "visitTryCatchFinally");
writeStatementLabel(statement);
MethodVisitor mv = controller.getMethodVisitor();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
Statement tryStatement = statement.getTryStatement();
final Statement finallyStatement = statement.getFinallyStatement();
// start try block, label needed for exception table
Label tryStart = new Label();
mv.visitLabel(tryStart);
BlockRecorder tryBlock = makeBlockRecorder(finallyStatement);
tryBlock.startRange(tryStart);
tryStatement.visit(controller.getAcg());
// goto finally part
Label finallyStart = new Label();
mv.visitJumpInsn(GOTO, finallyStart);
Label tryEnd = new Label();
mv.visitLabel(tryEnd);
tryBlock.closeRange(tryEnd);
// pop for "makeBlockRecorder(finallyStatement)"
controller.getCompileStack().pop();
BlockRecorder catches = makeBlockRecorder(finallyStatement);
for (CatchStatement catchStatement : statement.getCatchStatements()) {
ClassNode exceptionType = catchStatement.getExceptionType();
String exceptionTypeInternalName = BytecodeHelper.getClassInternalName(exceptionType);
// start catch block, label needed for exception table
Label catchStart = new Label();
mv.visitLabel(catchStart);
catches.startRange(catchStart);
// create exception variable and store the exception
Parameter exceptionVariable = catchStatement.getVariable();
compileStack.pushState();
compileStack.defineVariable(exceptionVariable, true);
// handle catch body
catchStatement.visit(controller.getAcg());
// place holder to avoid problems with empty catch blocks
mv.visitInsn(NOP);
// pop for the variable
controller.getCompileStack().pop();
// end of catch
Label catchEnd = new Label();
mv.visitLabel(catchEnd);
catches.closeRange(catchEnd);
// goto finally start
mv.visitJumpInsn(GOTO, finallyStart);
compileStack.writeExceptionTable(tryBlock, catchStart, exceptionTypeInternalName);
}
// Label used to handle exceptions in catches and regularly
// visited finals.
Label catchAny = new Label();
// add "catch any" block to exception table for try part we do this
// after the exception blocks, because else this one would supersede
// any of those otherwise
compileStack.writeExceptionTable(tryBlock, catchAny, null);
// same for the catch parts
compileStack.writeExceptionTable(catches, catchAny, null);
// pop for "makeBlockRecorder(catches)"
compileStack.pop();
// start finally
mv.visitLabel(finallyStart);
finallyStatement.visit(controller.getAcg());
//**
mv.visitInsn(NOP);
// goto after all-catching block
Label skipCatchAll = new Label();
mv.visitJumpInsn(GOTO, skipCatchAll);
// start a block catching any Exception
mv.visitLabel(catchAny);
//store exception
//TODO: maybe define a Throwable and use it here instead of Object
operandStack.push(ClassHelper.OBJECT_TYPE);
int anyExceptionIndex = compileStack.defineTemporaryVariable("exception", true);
finallyStatement.visit(controller.getAcg());
// load the exception and rethrow it
mv.visitVarInsn(ALOAD, anyExceptionIndex);
mv.visitInsn(ATHROW);
mv.visitLabel(skipCatchAll);
}
Aggregations