use of org.codehaus.groovy.ast.CodeVisitorSupport in project groovy by apache.
the class StaticTypesLambdaWriter method isAccessingInstanceMembersOfEnclosingClass.
private static boolean isAccessingInstanceMembersOfEnclosingClass(final MethodNode lambdaMethod) {
boolean[] result = new boolean[1];
ClassNode enclosingClass = lambdaMethod.getDeclaringClass().getOuterClass();
lambdaMethod.getCode().visit(new CodeVisitorSupport() {
@Override
public void visitVariableExpression(final VariableExpression expression) {
if (expression.isThisExpression() || enclosingClass.equals(expression.getNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER))) {
result[0] = true;
}
}
});
return result[0];
}
use of org.codehaus.groovy.ast.CodeVisitorSupport in project groovy by apache.
the class Verifier method visitConstructor.
@Override
public void visitConstructor(final ConstructorNode node) {
Statement stmt = node.getCode();
if (stmt != null) {
stmt.visit(new VerifierCodeVisitor(getClassNode()));
// check for uninitialized-this references
stmt.visit(new CodeVisitorSupport() {
@Override
public void visitClosureExpression(final ClosureExpression ce) {
boolean oldInClosure = inClosure;
inClosure = true;
super.visitClosureExpression(ce);
inClosure = oldInClosure;
}
@Override
public void visitConstructorCallExpression(final ConstructorCallExpression cce) {
boolean oldIsSpecialConstructorCall = inSpecialConstructorCall;
inSpecialConstructorCall |= cce.isSpecialCall();
super.visitConstructorCallExpression(cce);
inSpecialConstructorCall = oldIsSpecialConstructorCall;
}
@Override
public void visitMethodCallExpression(final MethodCallExpression mce) {
if (inSpecialConstructorCall && isThisObjectExpression(mce)) {
MethodNode methodTarget = mce.getMethodTarget();
if (methodTarget == null || !(methodTarget.isStatic() || classNode.getOuterClasses().contains(methodTarget.getDeclaringClass()))) {
if (!mce.isImplicitThis()) {
throw newVariableError(mce.getObjectExpression().getText(), mce.getObjectExpression());
} else {
throw newVariableError(mce.getMethodAsString(), mce.getMethod());
}
}
mce.getMethod().visit(this);
mce.getArguments().visit(this);
} else {
super.visitMethodCallExpression(mce);
}
}
@Override
public void visitVariableExpression(final VariableExpression ve) {
// before this/super ctor call completes, only params and static or outer members are accessible
if (inSpecialConstructorCall && (ve.isThisExpression() || ve.isSuperExpression() || isNonStaticMemberAccess(ve))) {
// TODO: context for default argument
throw newVariableError(ve.getName(), ve.getLineNumber() > 0 ? ve : node);
}
}
//
private boolean inClosure, inSpecialConstructorCall;
private boolean isNonStaticMemberAccess(final VariableExpression ve) {
Variable variable = ve.getAccessedVariable();
return !inClosure && variable != null && !isStatic(variable.getModifiers()) && !(variable instanceof DynamicVariable) && !(variable instanceof Parameter);
}
private boolean isThisObjectExpression(final MethodCallExpression mce) {
if (mce.isImplicitThis()) {
return true;
} else if (mce.getObjectExpression() instanceof VariableExpression) {
VariableExpression var = (VariableExpression) mce.getObjectExpression();
return var.isThisExpression() || var.isSuperExpression();
} else {
return false;
}
}
private GroovyRuntimeException newVariableError(final String name, final ASTNode node) {
RuntimeParserException rpe = new RuntimeParserException("Cannot reference '" + name + "' before supertype constructor has been called. Possible causes:\n" + "You attempted to access an instance field, method, or property.\n" + "You attempted to construct a non-static inner class.", node);
rpe.setModule(getClassNode().getModule());
return rpe;
}
});
}
}
use of org.codehaus.groovy.ast.CodeVisitorSupport in project groovy by apache.
the class Verifier method addDefaultParameterMethods.
/**
* Creates a new method for each combination of default parameter expressions.
*/
protected void addDefaultParameterMethods(final ClassNode type) {
List<MethodNode> methods = new ArrayList<>(type.getMethods());
addDefaultParameters(methods, (arguments, params, method) -> {
BlockStatement code = new BlockStatement();
MethodNode newMethod = new MethodNode(method.getName(), method.getModifiers(), method.getReturnType(), params, method.getExceptions(), code);
MethodNode oldMethod = type.getDeclaredMethod(method.getName(), params);
if (oldMethod != null) {
throw new RuntimeParserException("The method with default parameters \"" + method.getTypeDescriptor() + "\" defines a method \"" + newMethod.getTypeDescriptor() + "\" that is already defined.", sourceOf(method));
}
List<AnnotationNode> annotations = method.getAnnotations();
if (annotations != null && !annotations.isEmpty()) {
newMethod.addAnnotations(annotations);
}
newMethod.setGenericsTypes(method.getGenericsTypes());
// GROOVY-5632, GROOVY-9151: check for references to parameters that have been removed
GroovyCodeVisitor visitor = new CodeVisitorSupport() {
private boolean inClosure;
@Override
public void visitClosureExpression(final ClosureExpression e) {
boolean prev = inClosure;
inClosure = true;
super.visitClosureExpression(e);
inClosure = prev;
}
@Override
public void visitVariableExpression(final VariableExpression e) {
if (e.getAccessedVariable() instanceof Parameter) {
Parameter p = (Parameter) e.getAccessedVariable();
if (p.hasInitialExpression() && !Arrays.asList(params).contains(p)) {
VariableScope blockScope = code.getVariableScope();
VariableExpression localVariable = (VariableExpression) blockScope.getDeclaredVariable(p.getName());
if (localVariable == null) {
// create a variable declaration so that the name can be found in the new method
localVariable = localVarX(p.getName(), p.getType());
localVariable.setModifiers(p.getModifiers());
blockScope.putDeclaredVariable(localVariable);
localVariable.setInStaticContext(blockScope.isInStaticContext());
code.addStatement(declS(localVariable, p.getInitialExpression()));
}
if (!localVariable.isClosureSharedVariable()) {
localVariable.setClosureSharedVariable(inClosure);
}
}
}
}
};
visitor.visitArgumentlistExpression(arguments);
// if variable was created to capture an initial value expression, reference it in arguments as well
for (ListIterator<Expression> it = arguments.getExpressions().listIterator(); it.hasNext(); ) {
Expression argument = it.next();
if (argument instanceof CastExpression) {
argument = ((CastExpression) argument).getExpression();
}
for (Parameter p : method.getParameters()) {
if (p.hasInitialExpression() && p.getInitialExpression() == argument) {
if (code.getVariableScope().getDeclaredVariable(p.getName()) != null) {
it.set(varX(p.getName()));
}
break;
}
}
}
// delegate to original method using arguments derived from defaults
MethodCallExpression call = callThisX(method.getName(), arguments);
call.setMethodTarget(method);
call.setImplicitThis(true);
if (method.isVoidMethod()) {
code.addStatement(new ExpressionStatement(call));
} else {
code.addStatement(new ReturnStatement(call));
}
// GROOVY-5681: set anon. inner enclosing method reference
visitor = new CodeVisitorSupport() {
@Override
public void visitConstructorCallExpression(final ConstructorCallExpression call) {
if (call.isUsingAnonymousInnerClass()) {
call.getType().setEnclosingMethod(newMethod);
}
super.visitConstructorCallExpression(call);
}
};
visitor.visitBlockStatement(code);
addPropertyMethod(newMethod);
newMethod.putNodeMetaData(DEFAULT_PARAMETER_GENERATED, Boolean.TRUE);
});
}
use of org.codehaus.groovy.ast.CodeVisitorSupport in project groovy by apache.
the class InnerClassVisitor method isStatic.
private boolean isStatic(final ClassNode innerClass, final VariableScope scope, final ConstructorCallExpression call) {
boolean isStatic = innerClass.isStaticClass();
if (!isStatic) {
if (currentMethod != null) {
if (currentMethod instanceof ConstructorNode) {
boolean[] precedesSuperOrThisCall = new boolean[1];
ConstructorNode ctor = (ConstructorNode) currentMethod;
GroovyCodeVisitor visitor = new CodeVisitorSupport() {
@Override
public void visitConstructorCallExpression(ConstructorCallExpression cce) {
if (cce == call) {
precedesSuperOrThisCall[0] = true;
} else {
super.visitConstructorCallExpression(cce);
}
}
};
if (ctor.firstStatementIsSpecialConstructorCall())
currentMethod.getFirstStatement().visit(visitor);
Arrays.stream(ctor.getParameters()).filter(Parameter::hasInitialExpression).forEach(p -> p.getInitialExpression().visit(visitor));
isStatic = precedesSuperOrThisCall[0];
} else {
isStatic = currentMethod.isStatic();
}
} else if (currentField != null) {
isStatic = currentField.isStatic();
}
}
// GROOVY-8433: Category transform implies static method
isStatic = isStatic || innerClass.getOuterClass().getAnnotations().stream().anyMatch(a -> a.getClassNode().getName().equals("groovy.lang.Category"));
return isStatic;
}
use of org.codehaus.groovy.ast.CodeVisitorSupport in project groovy by apache.
the class EnumCompletionVisitor method getUniqueVariableName.
private String getUniqueVariableName(final String name, final Statement code) {
if (code == null)
return name;
final Object[] found = new Object[1];
CodeVisitorSupport cv = new CodeVisitorSupport() {
@Override
public void visitVariableExpression(VariableExpression expression) {
if (expression.getName().equals(name))
found[0] = Boolean.TRUE;
}
};
code.visit(cv);
if (found[0] != null)
return getUniqueVariableName("_" + name, code);
return name;
}
Aggregations