use of org.codehaus.groovy.syntax.SyntaxException in project groovy by apache.
the class StaticCompileTransformation method visit.
@Override
public void visit(final ASTNode[] nodes, final SourceUnit source) {
AnnotationNode annotationInformation = (AnnotationNode) nodes[0];
AnnotatedNode node = (AnnotatedNode) nodes[1];
StaticTypeCheckingVisitor visitor = null;
Map<String, Expression> members = annotationInformation.getMembers();
Expression extensions = members.get("extensions");
if (node instanceof ClassNode) {
ClassNode classNode = (ClassNode) node;
visitor = newVisitor(source, classNode);
visitor.setCompilationUnit(compilationUnit);
addTypeCheckingExtensions(visitor, extensions);
classNode.putNodeMetaData(WriterControllerFactory.class, factory);
node.putNodeMetaData(STATIC_COMPILE_NODE, !visitor.isSkipMode(node));
visitor.initialize();
visitor.visitClass(classNode);
} else if (node instanceof MethodNode) {
MethodNode methodNode = (MethodNode) node;
ClassNode declaringClass = methodNode.getDeclaringClass();
visitor = newVisitor(source, declaringClass);
visitor.setCompilationUnit(compilationUnit);
addTypeCheckingExtensions(visitor, extensions);
methodNode.putNodeMetaData(STATIC_COMPILE_NODE, !visitor.isSkipMode(node));
if (declaringClass.getNodeMetaData(WriterControllerFactory.class) == null) {
declaringClass.putNodeMetaData(WriterControllerFactory.class, factory);
}
visitor.setMethodsToBeVisited(Collections.singleton(methodNode));
visitor.initialize();
visitor.visitMethod(methodNode);
} else {
source.addError(new SyntaxException(STATIC_ERROR_PREFIX + "Unimplemented node type", node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()));
}
if (visitor != null) {
visitor.performSecondPass();
}
StaticCompilationTransformer transformer = new StaticCompilationTransformer(source, visitor);
if (node instanceof ClassNode) {
transformer.visitClass((ClassNode) node);
} else if (node instanceof MethodNode) {
transformer.visitMethod((MethodNode) node);
}
}
use of org.codehaus.groovy.syntax.SyntaxException in project groovy by apache.
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, classNode)) {
// 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;
}
Expression fixedReceiver = null;
boolean fixedImplicitThis = implicitThis;
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()));
} else if (!node.isDerivedFrom(target.getDeclaringClass()) && tryBridgeMethod(target, receiver, implicitThis, args, classNode)) {
return true;
}
} else if (target.isPublic() && receiver != null) {
if (implicitThis && !classNode.isDerivedFrom(target.getDeclaringClass()) && !classNode.implementsInterface(target.getDeclaringClass()) && classNode instanceof InnerClassNode && controller.isInClosure()) {
ClassNode current = classNode.getOuterClass();
fixedReceiver = new VariableExpression("thisObject", current);
// adjust for multiple levels of nesting if needed
while (current != null && current instanceof InnerClassNode && !classNode.equals(current)) {
FieldNode thisField = current.getField("this$0");
current = current.getOuterClass();
if (thisField != null) {
fixedReceiver = new PropertyExpression(fixedReceiver, "this$0");
fixedReceiver.setType(current);
fixedImplicitThis = false;
}
}
}
}
if (receiver != null) {
boolean callToSuper = receiver instanceof VariableExpression && ((VariableExpression) receiver).isSuperExpression();
if (!callToSuper) {
fixedReceiver = fixedReceiver == null ? receiver : fixedReceiver;
// 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(fixedReceiver, target);
return super.writeDirectMethodCall(target, fixedImplicitThis, checkCastReceiver, args);
}
}
return super.writeDirectMethodCall(target, implicitThis, receiver, args);
}
}
use of org.codehaus.groovy.syntax.SyntaxException in project groovy by apache.
the class InvocationWriter method makeMOPBasedConstructorCall.
private void makeMOPBasedConstructorCall(List<ConstructorNode> constructors, ConstructorCallExpression call, ClassNode callNode) {
MethodVisitor mv = controller.getMethodVisitor();
OperandStack operandStack = controller.getOperandStack();
call.getArguments().visit(controller.getAcg());
// keep Object[] on stack
mv.visitInsn(DUP);
// to select the constructor we need also the number of
// available constructors and the class we want to make
// the call on
BytecodeHelper.pushConstant(mv, -1);
controller.getAcg().visitClassExpression(new ClassExpression(callNode));
operandStack.remove(1);
// removes one Object[] leaves the int containing the
// call flags and the constructor number
selectConstructorAndTransformArguments.call(mv);
//load "this"
if (controller.isConstructor()) {
mv.visitVarInsn(ALOAD, 0);
} else {
mv.visitTypeInsn(NEW, BytecodeHelper.getClassInternalName(callNode));
}
mv.visitInsn(SWAP);
TreeMap<Integer, ConstructorNode> sortedConstructors = new TreeMap<Integer, ConstructorNode>();
for (ConstructorNode constructor : constructors) {
String typeDescriptor = BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, constructor.getParameters());
int hash = BytecodeHelper.hashCode(typeDescriptor);
ConstructorNode sameHashNode = sortedConstructors.put(hash, constructor);
if (sameHashNode != null) {
controller.getSourceUnit().addError(new SyntaxException("Unable to compile class " + controller.getClassNode().getName() + " due to hash collision in constructors", call.getLineNumber(), call.getColumnNumber()));
}
}
Label[] targets = new Label[constructors.size()];
int[] indices = new int[constructors.size()];
Iterator<Integer> hashIt = sortedConstructors.keySet().iterator();
Iterator<ConstructorNode> constructorIt = sortedConstructors.values().iterator();
for (int i = 0; i < targets.length; i++) {
targets[i] = new Label();
indices[i] = hashIt.next();
}
// create switch targets
Label defaultLabel = new Label();
Label afterSwitch = new Label();
mv.visitLookupSwitchInsn(defaultLabel, indices, targets);
for (int i = 0; i < targets.length; i++) {
mv.visitLabel(targets[i]);
// to extract the parameters.
if (controller.isConstructor()) {
// in this case we need one "this", so a SWAP will exchange
// "this" and Object[], a DUP_X1 will then copy the Object[]
/// to the last place in the stack:
// Object[],this -SWAP-> this,Object[]
// this,Object[] -DUP_X1-> Object[],this,Object[]
mv.visitInsn(SWAP);
mv.visitInsn(DUP_X1);
} else {
// in this case we need two "this" in between and the Object[]
// at the bottom of the stack as well as on top for our invokeSpecial
// So we do DUP_X1, DUP2_X1, POP
// Object[],this -DUP_X1-> this,Object[],this
// this,Object[],this -DUP2_X1-> Object[],this,this,Object[],this
// Object[],this,this,Object[],this -POP-> Object[],this,this,Object[]
mv.visitInsn(DUP_X1);
mv.visitInsn(DUP2_X1);
mv.visitInsn(POP);
}
ConstructorNode cn = constructorIt.next();
String descriptor = BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, cn.getParameters());
// unwrap the Object[] and make transformations if needed
// that means, to duplicate the Object[], make a cast with possible
// unboxing and then swap it with the Object[] for each parameter
// vargs need special attention and transformation though
Parameter[] parameters = cn.getParameters();
int lengthWithoutVargs = parameters.length;
if (parameters.length > 0 && parameters[parameters.length - 1].getType().isArray()) {
lengthWithoutVargs--;
}
for (int p = 0; p < lengthWithoutVargs; p++) {
loadAndCastElement(operandStack, mv, parameters, p);
}
if (parameters.length > lengthWithoutVargs) {
ClassNode type = parameters[lengthWithoutVargs].getType();
BytecodeHelper.pushConstant(mv, lengthWithoutVargs);
controller.getAcg().visitClassExpression(new ClassExpression(type));
operandStack.remove(1);
castToVargsArray.call(mv);
BytecodeHelper.doCast(mv, type);
} else {
// at the end we remove the Object[]
// the vargs case simply the last swap so no pop is needed
mv.visitInsn(POP);
}
// make the constructor call
mv.visitMethodInsn(INVOKESPECIAL, BytecodeHelper.getClassInternalName(callNode), "<init>", descriptor, false);
mv.visitJumpInsn(GOTO, afterSwitch);
}
mv.visitLabel(defaultLabel);
// this part should never be reached!
mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
mv.visitInsn(DUP);
mv.visitLdcInsn("This class has been compiled with a super class which is binary incompatible with the current super class found on classpath. You should recompile this class with the new version.");
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>", "(Ljava/lang/String;)V", false);
mv.visitInsn(ATHROW);
mv.visitLabel(afterSwitch);
// result on the stack, which we can remove now if inside a constructor.
if (!controller.isConstructor()) {
// in case we are not in a constructor we have an additional
// object on the stack, the result of our constructor call
// which we want to keep, so we swap with the dummy object and
// do normal removal of it. In the end, the call result will be
// on the stack then
mv.visitInsn(SWAP);
// for call result
operandStack.push(callNode);
}
mv.visitInsn(POP);
}
use of org.codehaus.groovy.syntax.SyntaxException in project groovy by apache.
the class CategoryASTTransformation method visit.
/**
* Property invocations done on 'this' reference are transformed so that the invocations at runtime are
* done on the additional parameter 'self'
*/
public void visit(ASTNode[] nodes, final SourceUnit source) {
if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof ClassNode)) {
source.getErrorCollector().addError(new SyntaxErrorMessage(new SyntaxException("@Category can only be added to a ClassNode but got: " + (nodes.length == 2 ? nodes[1] : "nothing"), nodes[0].getLineNumber(), nodes[0].getColumnNumber()), source));
}
AnnotationNode annotation = (AnnotationNode) nodes[0];
ClassNode parent = (ClassNode) nodes[1];
ClassNode targetClass = getTargetClass(source, annotation);
thisExpression.setType(targetClass);
final LinkedList<Set<String>> varStack = new LinkedList<Set<String>>();
if (!ensureNoInstanceFieldOrProperty(source, parent))
return;
Set<String> names = new HashSet<String>();
for (FieldNode field : parent.getFields()) {
names.add(field.getName());
}
for (PropertyNode field : parent.getProperties()) {
names.add(field.getName());
}
varStack.add(names);
final Reference parameter = new Reference();
final ClassCodeExpressionTransformer expressionTransformer = new ClassCodeExpressionTransformer() {
protected SourceUnit getSourceUnit() {
return source;
}
private void addVariablesToStack(Parameter[] params) {
Set<String> names = new HashSet<String>();
names.addAll(varStack.getLast());
for (Parameter param : params) {
names.add(param.getName());
}
varStack.add(names);
}
@Override
public void visitCatchStatement(CatchStatement statement) {
varStack.getLast().add(statement.getVariable().getName());
super.visitCatchStatement(statement);
varStack.getLast().remove(statement.getVariable().getName());
}
@Override
public void visitMethod(MethodNode node) {
addVariablesToStack(node.getParameters());
super.visitMethod(node);
varStack.removeLast();
}
@Override
public void visitBlockStatement(BlockStatement block) {
Set<String> names = new HashSet<String>();
names.addAll(varStack.getLast());
varStack.add(names);
super.visitBlockStatement(block);
varStack.remove(names);
}
@Override
public void visitClosureExpression(ClosureExpression ce) {
addVariablesToStack(ce.getParameters());
super.visitClosureExpression(ce);
varStack.removeLast();
}
@Override
public void visitDeclarationExpression(DeclarationExpression expression) {
if (expression.isMultipleAssignmentDeclaration()) {
TupleExpression te = expression.getTupleExpression();
List<Expression> list = te.getExpressions();
for (Expression arg : list) {
VariableExpression ve = (VariableExpression) arg;
varStack.getLast().add(ve.getName());
}
} else {
VariableExpression ve = expression.getVariableExpression();
varStack.getLast().add(ve.getName());
}
super.visitDeclarationExpression(expression);
}
@Override
public void visitForLoop(ForStatement forLoop) {
Expression exp = forLoop.getCollectionExpression();
exp.visit(this);
Parameter loopParam = forLoop.getVariable();
if (loopParam != null) {
varStack.getLast().add(loopParam.getName());
}
super.visitForLoop(forLoop);
}
@Override
public void visitExpressionStatement(ExpressionStatement es) {
// GROOVY-3543: visit the declaration expressions so that declaration variables get added on the varStack
Expression exp = es.getExpression();
if (exp instanceof DeclarationExpression) {
exp.visit(this);
}
super.visitExpressionStatement(es);
}
@Override
public Expression transform(Expression exp) {
if (exp instanceof VariableExpression) {
VariableExpression ve = (VariableExpression) exp;
if (ve.getName().equals("this"))
return thisExpression;
else {
if (!varStack.getLast().contains(ve.getName())) {
return new PropertyExpression(thisExpression, ve.getName());
}
}
} else if (exp instanceof PropertyExpression) {
PropertyExpression pe = (PropertyExpression) exp;
if (pe.getObjectExpression() instanceof VariableExpression) {
VariableExpression vex = (VariableExpression) pe.getObjectExpression();
if (vex.isThisExpression()) {
pe.setObjectExpression(thisExpression);
return pe;
}
}
} else if (exp instanceof ClosureExpression) {
ClosureExpression ce = (ClosureExpression) exp;
ce.getVariableScope().putReferencedLocalVariable((Parameter) parameter.get());
Parameter[] params = ce.getParameters();
if (params == null) {
params = Parameter.EMPTY_ARRAY;
} else if (params.length == 0) {
params = new Parameter[] { new Parameter(ClassHelper.OBJECT_TYPE, "it") };
}
addVariablesToStack(params);
ce.getCode().visit(this);
varStack.removeLast();
}
return super.transform(exp);
}
};
for (MethodNode method : parent.getMethods()) {
if (!method.isStatic()) {
method.setModifiers(method.getModifiers() | Opcodes.ACC_STATIC);
final Parameter[] origParams = method.getParameters();
final Parameter[] newParams = new Parameter[origParams.length + 1];
Parameter p = new Parameter(targetClass, "$this");
p.setClosureSharedVariable(true);
newParams[0] = p;
parameter.set(p);
System.arraycopy(origParams, 0, newParams, 1, origParams.length);
method.setParameters(newParams);
expressionTransformer.visitMethod(method);
}
}
new VariableScopeVisitor(source, true).visitClass(parent);
}
use of org.codehaus.groovy.syntax.SyntaxException in project gcontracts by andresteingress.
the class ProcessingContextInformation method addError.
public void addError(String msg, ASTNode expr) {
int line = expr.getLineNumber();
int col = expr.getColumnNumber();
SourceUnit source = sourceUnit();
source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(new SyntaxException(msg + '\n', line, col), source));
}
Aggregations