use of org.codehaus.groovy.ast.Parameter in project groovy by apache.
the class EnumCompletionVisitor method transformConstructor.
/**
* If constructor does not define a call to super, then transform constructor
* to get String,int parameters at beginning and add call super(String,int).
*/
private void transformConstructor(final ConstructorNode ctor) {
boolean chainedThisConstructorCall = false;
ConstructorCallExpression cce = null;
if (ctor.firstStatementIsSpecialConstructorCall()) {
Statement code = ctor.getFirstStatement();
cce = (ConstructorCallExpression) ((ExpressionStatement) code).getExpression();
if (cce.isSuperCall())
return;
// must be call to this(...)
chainedThisConstructorCall = true;
}
// we need to add parameters
Parameter[] oldP = ctor.getParameters();
Parameter[] newP = new Parameter[oldP.length + 2];
String stringParameterName = getUniqueVariableName("__str", ctor.getCode());
newP[0] = new Parameter(ClassHelper.STRING_TYPE, stringParameterName);
String intParameterName = getUniqueVariableName("__int", ctor.getCode());
newP[1] = new Parameter(ClassHelper.int_TYPE, intParameterName);
System.arraycopy(oldP, 0, newP, 2, oldP.length);
ctor.setParameters(newP);
VariableExpression stringVariable = new VariableExpression(newP[0]);
VariableExpression intVariable = new VariableExpression(newP[1]);
if (chainedThisConstructorCall) {
TupleExpression args = (TupleExpression) cce.getArguments();
List<Expression> argsExprs = args.getExpressions();
argsExprs.add(0, stringVariable);
argsExprs.add(1, intVariable);
} else {
// add a super call
List<Expression> args = new ArrayList<>();
args.add(stringVariable);
args.add(intVariable);
if (EnumVisitor.isAnonymousInnerClass(ctor.getDeclaringClass())) {
for (Parameter parameter : oldP) {
args.add(new VariableExpression(parameter));
}
ClassNode enumClass = ctor.getDeclaringClass().getSuperClass();
// GROOVY-6747: bridge enum's private constructor
makeBridgeConstructor(enumClass, newP);
args.add(new CastExpression(enumClass.getPlainNodeReference(), ConstantExpression.NULL));
}
cce = new ConstructorCallExpression(ClassNode.SUPER, new ArgumentListExpression(args));
BlockStatement code = new BlockStatement();
code.addStatement(new ExpressionStatement(cce));
Statement oldCode = ctor.getCode();
if (oldCode != null)
code.addStatement(oldCode);
ctor.setCode(code);
}
}
use of org.codehaus.groovy.ast.Parameter in project groovy by apache.
the class InnerClassVisitor method visitConstructorCallExpression.
@Override
public void visitConstructorCallExpression(ConstructorCallExpression call) {
super.visitConstructorCallExpression(call);
if (!call.isUsingAnonymousInnerClass()) {
passThisReference(call);
return;
}
InnerClassNode innerClass = (InnerClassNode) call.getType();
ClassNode outerClass = innerClass.getOuterClass();
ClassNode superClass = innerClass.getSuperClass();
if (!superClass.isInterface() && superClass.getOuterClass() != null && !(superClass.isStaticClass() || (superClass.getModifiers() & ACC_STATIC) != 0)) {
insertThis0ToSuperCall(call, innerClass);
}
if (!innerClass.getDeclaredConstructors().isEmpty())
return;
if ((innerClass.getModifiers() & ACC_STATIC) != 0)
return;
VariableScope scope = innerClass.getVariableScope();
if (scope == null)
return;
boolean isStatic = !inClosure && isStatic(innerClass, scope, call);
// expressions = constructor call arguments
List<Expression> expressions = ((TupleExpression) call.getArguments()).getExpressions();
// block = init code for the constructor we produce
BlockStatement block = new BlockStatement();
// parameters = parameters of the constructor
int additionalParamCount = (isStatic ? 0 : 1) + scope.getReferencedLocalVariablesCount();
List<Parameter> parameters = new ArrayList<>(expressions.size() + additionalParamCount);
// superCallArguments = arguments for the super call == the constructor call arguments
List<Expression> superCallArguments = new ArrayList<>(expressions.size());
// first we add a super() call for all expressions given in the constructor call expression
for (int i = 0, n = expressions.size(); i < n; i += 1) {
// add one parameter for each expression in the constructor call
Parameter param = new Parameter(ClassHelper.OBJECT_TYPE, "p" + additionalParamCount + i);
parameters.add(param);
// add the corresponding argument to the super constructor call
superCallArguments.add(new VariableExpression(param));
}
// add the super call
ConstructorCallExpression cce = new ConstructorCallExpression(ClassNode.SUPER, new TupleExpression(superCallArguments));
block.addStatement(new ExpressionStatement(cce));
int pCount = 0;
if (!isStatic) {
// need to pass "this" to access unknown methods/properties
ClassNode enclosingType = (inClosure ? ClassHelper.CLOSURE_TYPE : outerClass).getPlainNodeReference();
expressions.add(pCount, new VariableExpression("this", enclosingType));
Parameter thisParameter = new Parameter(enclosingType, "p" + pCount);
parameters.add(pCount++, thisParameter);
// "this" reference is saved in a field named "this$0"
FieldNode thisField = innerClass.addField("this$0", ACC_FINAL | ACC_SYNTHETIC, enclosingType, null);
addFieldInit(thisParameter, thisField, block);
}
// for each shared variable, add a Reference field
for (Iterator<Variable> it = scope.getReferencedLocalVariablesIterator(); it.hasNext(); ) {
Variable var = it.next();
VariableExpression ve = new VariableExpression(var);
ve.setClosureSharedVariable(true);
ve.setUseReferenceDirectly(true);
expressions.add(pCount, ve);
ClassNode referenceType = ClassHelper.REFERENCE_TYPE.getPlainNodeReference();
Parameter p = new Parameter(referenceType, "p" + pCount);
p.setOriginType(var.getOriginType());
parameters.add(pCount++, p);
VariableExpression initial = new VariableExpression(p);
initial.setSynthetic(true);
initial.setUseReferenceDirectly(true);
FieldNode pField = innerClass.addFieldFirst(ve.getName(), ACC_PUBLIC | ACC_SYNTHETIC, referenceType, initial);
pField.setHolder(true);
pField.setOriginType(ClassHelper.getWrapper(var.getOriginType()));
}
innerClass.addConstructor(ACC_SYNTHETIC, parameters.toArray(Parameter.EMPTY_ARRAY), ClassNode.EMPTY_ARRAY, block);
}
use of org.codehaus.groovy.ast.Parameter in project groovy by apache.
the class StaticTypesMethodReferenceExpressionWriter method createParametersWithExactType.
private Parameter[] createParametersWithExactType(final MethodNode abstractMethod, final ClassNode[] inferredParamTypes) {
// MUST clone the parameters to avoid impacting the original parameter type of SAM
Parameter[] parameters = GeneralUtils.cloneParams(abstractMethod.getParameters());
if (inferredParamTypes != null) {
for (int i = 0, n = parameters.length; i < n; i += 1) {
ClassNode inferredParamType = inferredParamTypes[i];
if (inferredParamType == null)
continue;
Parameter parameter = parameters[i];
Parameter targetParameter = parameter;
ClassNode type = convertParameterType(targetParameter.getType(), parameter.getType(), inferredParamType);
parameter.setOriginType(type);
parameter.setType(type);
}
}
return parameters;
}
use of org.codehaus.groovy.ast.Parameter in project groovy by apache.
the class StaticVerifier method visitConstructorOrMethod.
@Override
public void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
MethodNode oldMethodNode = methodNode;
methodNode = node;
super.visitConstructorOrMethod(node, isConstructor);
if (isConstructor) {
for (Parameter param : node.getParameters()) {
if (param.hasInitialExpression()) {
// initial expression will be argument to special constructor call
boolean oldIsSpecialConstructorCall = inSpecialConstructorCall;
inSpecialConstructorCall = true;
param.getInitialExpression().visit(this);
inSpecialConstructorCall = oldIsSpecialConstructorCall;
}
}
}
methodNode = oldMethodNode;
}
use of org.codehaus.groovy.ast.Parameter in project groovy by apache.
the class Verifier method addGroovyObjectInterfaceAndMethods.
protected void addGroovyObjectInterfaceAndMethods(final ClassNode node, final String classInternalName) {
if (!node.isDerivedFromGroovyObject())
node.addInterface(ClassHelper.make(GroovyObject.class));
FieldNode metaClassField = getMetaClassField(node);
boolean shouldAnnotate = classNode.getModule().getContext() != null;
AnnotationNode generatedAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(GENERATED_ANNOTATION)) : null;
AnnotationNode internalAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(INTERNAL_ANNOTATION)) : null;
AnnotationNode transientAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(TRANSIENT_ANNOTATION)) : null;
if (!node.hasMethod("getMetaClass", Parameter.EMPTY_ARRAY)) {
metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
MethodNode methodNode = addMethod(node, !shouldAnnotate, "getMetaClass", ACC_PUBLIC, ClassHelper.METACLASS_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
@Override
public void visit(final MethodVisitor mv) {
Label nullLabel = new Label();
/*
* the code is:
* if (this.metaClass==null) {
* this.metaClass = this.$getStaticMetaClass()
* return this.metaClass
* } else {
* return this.metaClass
* }
* with the optimization that the result of the
* first this.metaClass is duped on the operand
* stack and reused for the return in the else part
*/
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(DUP);
mv.visitJumpInsn(IFNULL, nullLabel);
mv.visitInsn(ARETURN);
mv.visitLabel(nullLabel);
mv.visitInsn(POP);
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(ARETURN);
}
}));
if (shouldAnnotate) {
methodNode.addAnnotation(generatedAnnotation);
methodNode.addAnnotation(internalAnnotation);
methodNode.addAnnotation(transientAnnotation);
}
}
Parameter[] parameters = new Parameter[] { new Parameter(ClassHelper.METACLASS_TYPE, "mc") };
if (!node.hasMethod("setMetaClass", parameters)) {
metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
Statement setMetaClassCode;
if (isFinal(metaClassField.getModifiers())) {
ConstantExpression text = new ConstantExpression("cannot set read-only meta class");
ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
setMetaClassCode = new ExpressionStatement(cce);
} else {
setMetaClassCode = new BytecodeSequence(new BytecodeInstruction() {
@Override
public void visit(final MethodVisitor mv) {
/*
* the code is (meta class is stored in 1):
* this.metaClass = <1>
*/
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(RETURN);
}
});
}
MethodNode methodNode = addMethod(node, !shouldAnnotate, "setMetaClass", ACC_PUBLIC, ClassHelper.VOID_TYPE, SET_METACLASS_PARAMS, ClassNode.EMPTY_ARRAY, setMetaClassCode);
if (shouldAnnotate) {
methodNode.addAnnotation(generatedAnnotation);
methodNode.addAnnotation(internalAnnotation);
}
}
}
Aggregations