use of groovy.lang.Reference in project groovy by apache.
the class BindPathSnooper method createBinding.
public FullBinding createBinding(SourceBinding source, TargetBinding target) {
if (source != this) {
throw new RuntimeException("Source binding must the Trigger Binding as well");
}
final BindPathSnooper delegate = new BindPathSnooper();
try {
// create our own local copy of the closure
final Class closureClass = closure.getClass();
// do in privileged block since we may be looking at private stuff
Closure closureLocalCopy = java.security.AccessController.doPrivileged(new PrivilegedAction<Closure>() {
public Closure run() {
// assume closures have only 1 constructor, of the form (Object, Reference*)
Constructor constructor = closureClass.getConstructors()[0];
int paramCount = constructor.getParameterTypes().length;
Object[] args = new Object[paramCount];
args[0] = delegate;
for (int i = 1; i < paramCount; i++) {
args[i] = new Reference(new BindPathSnooper());
}
try {
boolean acc = constructor.isAccessible();
constructor.setAccessible(true);
Closure localCopy = (Closure) constructor.newInstance(args);
if (!acc) {
constructor.setAccessible(false);
}
localCopy.setResolveStrategy(Closure.DELEGATE_ONLY);
for (Field f : closureClass.getDeclaredFields()) {
acc = f.isAccessible();
f.setAccessible(true);
if (f.getType() == Reference.class) {
delegate.fields.put(f.getName(), (BindPathSnooper) ((Reference) f.get(localCopy)).get());
}
if (!acc) {
f.setAccessible(false);
}
}
return localCopy;
} catch (Exception e) {
throw new RuntimeException("Error snooping closure", e);
}
}
});
try {
closureLocalCopy.call();
} catch (DeadEndException e) {
// we want this exception exposed.
throw e;
} catch (Exception e) {
//LOGME
// ignore it, likely failing because we are faking out properties
// such as a call to Math.min(int, BindPathSnooper)
}
} catch (Exception e) {
e.printStackTrace(System.out);
throw new RuntimeException("A closure expression binding could not be created because of " + e.getClass().getName() + ":\n\t" + e.getMessage());
}
List<BindPath> rootPaths = new ArrayList<BindPath>();
for (Map.Entry<String, BindPathSnooper> entry : delegate.fields.entrySet()) {
BindPath bp = createBindPath(entry.getKey(), entry.getValue());
bp.currentObject = closure;
rootPaths.add(bp);
}
PropertyPathFullBinding fb = new PropertyPathFullBinding();
fb.setSourceBinding(new ClosureSourceBinding(closure));
fb.setTargetBinding(target);
fb.bindPaths = rootPaths.toArray(new BindPath[rootPaths.size()]);
return fb;
}
use of groovy.lang.Reference in project groovy by apache.
the class StaticCompilationVisitor method existsProperty.
@Override
protected boolean existsProperty(final PropertyExpression pexp, final boolean checkForReadOnly, final ClassCodeVisitorSupport visitor) {
Expression objectExpression = pexp.getObjectExpression();
ClassNode objectExpressionType = getType(objectExpression);
Reference<ClassNode> rType = new Reference<>(objectExpressionType);
ClassCodeVisitorSupport receiverMemoizer = new ClassCodeVisitorSupport() {
@Override
protected SourceUnit getSourceUnit() {
return null;
}
@Override
public void visitField(final FieldNode node) {
if (visitor != null)
visitor.visitField(node);
ClassNode declaringClass = node.getDeclaringClass();
if (declaringClass != null) {
if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(declaringClass, LIST_TYPE)) {
boolean spread = declaringClass.getDeclaredField(node.getName()) != node;
pexp.setSpreadSafe(spread);
}
rType.set(declaringClass);
}
}
@Override
public void visitMethod(final MethodNode node) {
if (visitor != null)
visitor.visitMethod(node);
ClassNode declaringClass = node.getDeclaringClass();
if (declaringClass != null) {
if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(declaringClass, LIST_TYPE)) {
List<MethodNode> properties = declaringClass.getDeclaredMethods(node.getName());
boolean spread = true;
for (MethodNode mn : properties) {
if (node == mn) {
spread = false;
break;
}
}
// it's no real property but a property of the component
pexp.setSpreadSafe(spread);
}
rType.set(declaringClass);
}
}
@Override
public void visitProperty(final PropertyNode node) {
if (visitor != null)
visitor.visitProperty(node);
ClassNode declaringClass = node.getDeclaringClass();
if (declaringClass != null) {
if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(declaringClass, LIST_TYPE)) {
List<PropertyNode> properties = declaringClass.getProperties();
boolean spread = true;
for (PropertyNode propertyNode : properties) {
if (propertyNode == node) {
spread = false;
break;
}
}
// it's no real property but a property of the component
pexp.setSpreadSafe(spread);
}
rType.set(declaringClass);
}
}
};
boolean exists = super.existsProperty(pexp, checkForReadOnly, receiverMemoizer);
if (exists) {
objectExpressionType = rType.get();
if (objectExpression.getNodeMetaData(PROPERTY_OWNER) == null) {
objectExpression.putNodeMetaData(PROPERTY_OWNER, objectExpressionType);
}
if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(objectExpressionType, LIST_TYPE)) {
objectExpression.putNodeMetaData(COMPONENT_TYPE, inferComponentType(objectExpressionType, int_TYPE));
}
}
return exists;
}
use of groovy.lang.Reference in project groovy by apache.
the class CategoryASTTransformation method transformReferencesToThis.
// --------------------------------------------------------------------------
private void transformReferencesToThis(final ClassNode targetClass, final ClassNode sourceClass, final SourceUnit sourceUnit) {
final Reference<Parameter> selfParameter = new Reference<>();
final LinkedList<Set<String>> varStack = new LinkedList<>();
Set<String> names = new HashSet<>();
for (FieldNode fn : sourceClass.getFields()) names.add(fn.getName());
for (PropertyNode pn : sourceClass.getProperties()) names.add(pn.getName());
varStack.add(names);
ClassCodeExpressionTransformer transformer = new ClassCodeExpressionTransformer() {
// GROOVY-6510: track closure containment
private boolean inClosure;
private void addVariablesToStack(final Parameter[] parameter) {
Set<String> names = new HashSet<>(varStack.getLast());
for (Parameter p : parameter) names.add(p.getName());
varStack.add(names);
}
private Expression createThisExpression() {
VariableExpression ve = new VariableExpression("$this", targetClass);
ve.setClosureSharedVariable(true);
return ve;
}
@Override
protected SourceUnit getSourceUnit() {
return sourceUnit;
}
@Override
public Expression transform(final Expression expression) {
if (expression instanceof VariableExpression) {
VariableExpression ve = (VariableExpression) expression;
if (ve.isThisExpression()) {
Expression thisExpression = createThisExpression();
thisExpression.setSourcePosition(ve);
return thisExpression;
} else if (!inClosure && !ve.isSuperExpression() && !varStack.getLast().contains(ve.getName())) {
PropertyExpression pe = new PropertyExpression(createThisExpression(), ve.getName());
pe.setSourcePosition(ve);
return pe;
}
} else if (expression instanceof MethodCallExpression) {
MethodCallExpression mce = (MethodCallExpression) expression;
if (inClosure && mce.isImplicitThis() && isThisExpression(mce.getObjectExpression())) {
// GROOVY-6510: preserve implicit-this semantics
mce.setArguments(transform(mce.getArguments()));
mce.setMethod(transform(mce.getMethod()));
return mce;
}
} else if (expression instanceof ClosureExpression) {
ClosureExpression ce = (ClosureExpression) expression;
addVariablesToStack(hasImplicitParameter(ce) ? params(param(ClassHelper.OBJECT_TYPE, "it")) : getParametersSafe(ce));
ce.getVariableScope().putReferencedLocalVariable(selfParameter.get());
addAll(varStack.getLast(), "owner", "delegate", "thisObject");
boolean closure = inClosure;
inClosure = true;
ce.getCode().visit(this);
varStack.removeLast();
inClosure = closure;
}
return super.transform(expression);
}
@Override
public void visitBlockStatement(final BlockStatement statement) {
Set<String> names = new HashSet<>(varStack.getLast());
varStack.add(names);
super.visitBlockStatement(statement);
varStack.remove(names);
}
@Override
public void visitCatchStatement(final CatchStatement statement) {
varStack.getLast().add(statement.getVariable().getName());
super.visitCatchStatement(statement);
varStack.getLast().remove(statement.getVariable().getName());
}
@Override
public void visitClosureExpression(final ClosureExpression expression) {
}
@Override
public void visitDeclarationExpression(final DeclarationExpression expression) {
if (expression.isMultipleAssignmentDeclaration()) {
for (Expression e : expression.getTupleExpression().getExpressions()) {
VariableExpression ve = (VariableExpression) e;
varStack.getLast().add(ve.getName());
}
} else {
VariableExpression ve = expression.getVariableExpression();
varStack.getLast().add(ve.getName());
}
super.visitDeclarationExpression(expression);
}
@Override
public void visitExpressionStatement(final ExpressionStatement statement) {
// GROOVY-3543: visit the declaration expressions so that declaration variables get added on the varStack
if (statement.getExpression() instanceof DeclarationExpression) {
statement.getExpression().visit(this);
}
super.visitExpressionStatement(statement);
}
@Override
public void visitForLoop(final ForStatement statement) {
Expression exp = statement.getCollectionExpression();
exp.visit(this);
Parameter loopParam = statement.getVariable();
if (loopParam != null) {
varStack.getLast().add(loopParam.getName());
}
super.visitForLoop(statement);
}
@Override
public void visitMethod(final MethodNode node) {
addVariablesToStack(node.getParameters());
super.visitMethod(node);
varStack.removeLast();
}
};
for (MethodNode method : sourceClass.getMethods()) {
if (!method.isStatic()) {
Parameter p = new Parameter(targetClass, "$this");
p.setClosureSharedVariable(true);
selfParameter.set(p);
Parameter[] oldParams = method.getParameters();
Parameter[] newParams = new Parameter[oldParams.length + 1];
newParams[0] = p;
System.arraycopy(oldParams, 0, newParams, 1, oldParams.length);
method.setModifiers(method.getModifiers() | Opcodes.ACC_STATIC);
method.setParameters(newParams);
transformer.visitMethod(method);
}
}
}
use of groovy.lang.Reference in project groovy by apache.
the class DelegateASTTransformation method addGetterIfNeeded.
private static void addGetterIfNeeded(final DelegateDescription delegate, final PropertyNode prop, final String name, final boolean allNames) {
boolean isPrimBool = isPrimitiveBoolean(prop.getOriginType());
// do a little bit of pre-work since Groovy compiler hasn't added property accessors yet
boolean willHaveGetAccessor = true;
boolean willHaveIsAccessor = isPrimBool;
String getterName = getGetterName(name);
String isserName = getPredicateName(name);
if (isPrimBool) {
ClassNode cNode = prop.getDeclaringClass();
if (cNode.getGetterMethod(isserName) != null && cNode.getGetterMethod(getterName) == null)
willHaveGetAccessor = false;
if (cNode.getGetterMethod(getterName) != null && cNode.getGetterMethod(isserName) == null)
willHaveIsAccessor = false;
}
Reference<Boolean> ownerWillHaveGetAccessor = new Reference<Boolean>();
Reference<Boolean> ownerWillHaveIsAccessor = new Reference<Boolean>();
extractAccessorInfo(delegate.owner, name, ownerWillHaveGetAccessor, ownerWillHaveIsAccessor);
if (willHaveGetAccessor && !ownerWillHaveGetAccessor.get() && !shouldSkipPropertyMethod(name, getterName, delegate.excludes, delegate.includes, allNames)) {
addGeneratedMethod(delegate.owner, getterName, ACC_PUBLIC, nonGeneric(prop.getType()), Parameter.EMPTY_ARRAY, null, returnS(propX(delegate.getOp, name)));
}
if (willHaveIsAccessor && !ownerWillHaveIsAccessor.get() && !shouldSkipPropertyMethod(name, getterName, delegate.excludes, delegate.includes, allNames)) {
addGeneratedMethod(delegate.owner, isserName, ACC_PUBLIC, nonGeneric(prop.getType()), Parameter.EMPTY_ARRAY, null, returnS(propX(delegate.getOp, name)));
}
}
use of groovy.lang.Reference in project groovy by apache.
the class BindPathSnooper method createBinding.
@Override
public FullBinding createBinding(SourceBinding source, TargetBinding target) {
if (source != this) {
throw new RuntimeException("Source binding must the Trigger Binding as well");
}
final BindPathSnooper delegate = new BindPathSnooper();
try {
// create our own local copy of the closure
final Class closureClass = closure.getClass();
// do in privileged block since we may be looking at private stuff
Closure closureLocalCopy = VMPluginFactory.getPlugin().doPrivileged(new PrivilegedAction<Closure>() {
@Override
public Closure run() {
// assume closures have only 1 constructor, of the form (Object, Reference*)
Constructor constructor = closureClass.getConstructors()[0];
int paramCount = constructor.getParameterTypes().length;
Object[] args = new Object[paramCount];
args[0] = delegate;
for (int i = 1; i < paramCount; i++) {
args[i] = new Reference<Object>(new BindPathSnooper());
}
try {
boolean acc = isAccessible(constructor);
ReflectionUtils.trySetAccessible(constructor);
Closure localCopy = (Closure) constructor.newInstance(args);
if (!acc) {
constructor.setAccessible(false);
}
localCopy.setResolveStrategy(Closure.DELEGATE_ONLY);
for (Field f : closureClass.getDeclaredFields()) {
acc = isAccessible(f);
ReflectionUtils.trySetAccessible(f);
if (f.getType() == Reference.class) {
delegate.fields.put(f.getName(), (BindPathSnooper) ((Reference) f.get(localCopy)).get());
}
if (!acc) {
f.setAccessible(false);
}
}
return localCopy;
} catch (Exception e) {
throw new RuntimeException("Error snooping closure", e);
}
}
});
try {
closureLocalCopy.call();
} catch (DeadEndException e) {
// we want this exception exposed.
throw e;
} catch (Exception e) {
// LOGME
// ignore it, likely failing because we are faking out properties
// such as a call to Math.min(int, BindPathSnooper)
}
} catch (Exception e) {
e.printStackTrace(System.out);
throw new RuntimeException("A closure expression binding could not be created because of " + e.getClass().getName() + ":\n\t" + e.getMessage());
}
List<BindPath> rootPaths = new ArrayList<BindPath>();
for (Map.Entry<String, BindPathSnooper> entry : delegate.fields.entrySet()) {
BindPath bp = createBindPath(entry.getKey(), entry.getValue());
bp.currentObject = closure;
rootPaths.add(bp);
}
PropertyPathFullBinding fb = new PropertyPathFullBinding();
fb.setSourceBinding(new ClosureSourceBinding(closure));
fb.setTargetBinding(target);
fb.bindPaths = rootPaths.toArray(EMPTY_BINDPATH_ARRAY);
return fb;
}
Aggregations