use of org.codehaus.groovy.ast.MethodNode in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method addListAssignmentConstructorErrors.
private void addListAssignmentConstructorErrors(ClassNode leftRedirect, ClassNode leftExpressionType, ClassNode inferredRightExpressionType, Expression rightExpression, Expression assignmentExpression) {
// In that case, more checks can be performed
if (rightExpression instanceof ListExpression && !implementsInterfaceOrIsSubclassOf(LIST_TYPE, leftRedirect)) {
ArgumentListExpression argList = new ArgumentListExpression(((ListExpression) rightExpression).getExpressions());
ClassNode[] args = getArgumentTypes(argList);
MethodNode methodNode = checkGroovyStyleConstructor(leftRedirect, args, assignmentExpression);
if (methodNode != null) {
rightExpression.putNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET, methodNode);
}
} else if (!implementsInterfaceOrIsSubclassOf(inferredRightExpressionType, leftRedirect) && implementsInterfaceOrIsSubclassOf(inferredRightExpressionType, LIST_TYPE) && !isWildcardLeftHandSide(leftExpressionType)) {
if (!extension.handleIncompatibleAssignment(leftExpressionType, inferredRightExpressionType, assignmentExpression)) {
addAssignmentError(leftExpressionType, inferredRightExpressionType, assignmentExpression);
}
}
}
use of org.codehaus.groovy.ast.MethodNode in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method visitClass.
@Override
public void visitClass(final ClassNode node) {
if (shouldSkipClassNode(node))
return;
if (extension.beforeVisitClass(node)) {
extension.afterVisitClass(node);
return;
}
Object type = node.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
if (type != null) {
// transformation has already been run on this class node
// so we'll use a silent collector in order not to duplicate errors
typeCheckingContext.pushErrorCollector();
}
typeCheckingContext.pushEnclosingClassNode(node);
Set<MethodNode> oldVisitedMethod = typeCheckingContext.alreadyVisitedMethods;
typeCheckingContext.alreadyVisitedMethods = new LinkedHashSet<MethodNode>();
super.visitClass(node);
Iterator<InnerClassNode> innerClasses = node.getInnerClasses();
while (innerClasses.hasNext()) {
InnerClassNode innerClassNode = innerClasses.next();
visitClass(innerClassNode);
}
typeCheckingContext.alreadyVisitedMethods = oldVisitedMethod;
node.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, node);
// works in a two pass sequence and we don't want to skip the second pass
for (MethodNode methodNode : node.getMethods()) {
methodNode.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE);
}
for (ConstructorNode constructorNode : node.getDeclaredConstructors()) {
constructorNode.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE);
}
extension.afterVisitClass(node);
}
use of org.codehaus.groovy.ast.MethodNode in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method addGeneratedMethods.
private List<MethodNode> addGeneratedMethods(final ClassNode receiver, final List<MethodNode> methods) {
// using a comparator of parameters
List<MethodNode> result = new LinkedList<MethodNode>();
for (MethodNode method : methods) {
result.add(method);
Parameter[] parameters = method.getParameters();
int counter = 0;
int size = parameters.length;
for (int i = size - 1; i >= 0; i--) {
Parameter parameter = parameters[i];
if (parameter != null && parameter.hasInitialExpression()) {
counter++;
}
}
for (int j = 1; j <= counter; j++) {
Parameter[] newParams = new Parameter[parameters.length - j];
int index = 0;
int k = 1;
for (int i = 0; i < parameters.length; i++) {
if (k > counter - j && parameters[i] != null && parameters[i].hasInitialExpression()) {
k++;
} else if (parameters[i] != null && parameters[i].hasInitialExpression()) {
newParams[index++] = parameters[i];
k++;
} else {
newParams[index++] = parameters[i];
}
}
MethodNode stubbed;
if ("<init>".equals(method.getName())) {
stubbed = new ConstructorNode(method.getModifiers(), newParams, method.getExceptions(), GENERATED_EMPTY_STATEMENT);
} else {
stubbed = new MethodNode(method.getName(), method.getModifiers(), method.getReturnType(), newParams, method.getExceptions(), GENERATED_EMPTY_STATEMENT);
stubbed.setGenericsTypes(method.getGenericsTypes());
}
stubbed.setDeclaringClass(receiver);
result.add(stubbed);
}
}
return result;
}
use of org.codehaus.groovy.ast.MethodNode in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method findMethod.
protected List<MethodNode> findMethod(ClassNode receiver, String name, ClassNode... args) {
if (isPrimitiveType(receiver))
receiver = getWrapper(receiver);
List<MethodNode> methods;
if (!receiver.isInterface() && "<init>".equals(name)) {
methods = addGeneratedMethods(receiver, new ArrayList<MethodNode>(receiver.getDeclaredConstructors()));
if (methods.isEmpty()) {
MethodNode node = new ConstructorNode(Opcodes.ACC_PUBLIC, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
node.setDeclaringClass(receiver);
return Collections.singletonList(node);
}
} else {
methods = findMethodsWithGenerated(receiver, name);
if (receiver.isInterface()) {
collectAllInterfaceMethodsByName(receiver, name, methods);
methods.addAll(OBJECT_TYPE.getMethods(name));
}
if (typeCheckingContext.getEnclosingClosure() == null) {
// not in a closure
ClassNode parent = receiver;
while (parent instanceof InnerClassNode && !parent.isStaticClass()) {
parent = parent.getOuterClass();
methods.addAll(findMethodsWithGenerated(parent, name));
}
}
if (methods.isEmpty()) {
addArrayMethods(methods, receiver, name, args);
}
if (methods.isEmpty() && (args == null || args.length == 0)) {
// check if it's a property
String pname = extractPropertyNameFromMethodName("get", name);
if (pname == null) {
pname = extractPropertyNameFromMethodName("is", name);
}
if (pname != null) {
// we don't use property exists there because findMethod is called on super clases recursively
PropertyNode property = null;
ClassNode curNode = receiver;
while (property == null && curNode != null) {
property = curNode.getProperty(pname);
ClassNode svCur = curNode;
while (property == null && svCur instanceof InnerClassNode && !svCur.isStaticClass()) {
svCur = svCur.getOuterClass();
property = svCur.getProperty(pname);
if (property != null) {
receiver = svCur;
break;
}
}
curNode = curNode.getSuperClass();
}
if (property != null) {
MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC, property.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
if (property.isStatic()) {
node.setModifiers(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC);
}
node.setDeclaringClass(receiver);
return Collections.singletonList(node);
}
}
} else if (methods.isEmpty() && args != null && args.length == 1) {
// maybe we are looking for a setter ?
String pname = extractPropertyNameFromMethodName("set", name);
if (pname != null) {
ClassNode curNode = receiver;
PropertyNode property = null;
while (property == null && curNode != null) {
property = curNode.getProperty(pname);
curNode = curNode.getSuperClass();
}
if (property != null) {
ClassNode type = property.getOriginType();
if (implementsInterfaceOrIsSubclassOf(wrapTypeIfNecessary(args[0]), wrapTypeIfNecessary(type))) {
MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC, VOID_TYPE, new Parameter[] { new Parameter(type, "arg") }, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
if (property.isStatic()) {
node.setModifiers(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC);
}
node.setDeclaringClass(receiver);
return Collections.singletonList(node);
}
}
}
}
}
if (methods.isEmpty()) {
// look at the interfaces, there's a chance that a method is not implemented and we should not hide the
// error from the compiler
collectAllInterfaceMethodsByName(receiver, name, methods);
}
// lookup in DGM methods too
findDGMMethodsByNameAndArguments(getTransformLoader(), receiver, name, args, methods);
List<MethodNode> chosen = chooseBestMethod(receiver, methods, args);
if (!chosen.isEmpty())
return chosen;
// GROOVY-5566
if (receiver instanceof InnerClassNode && ((InnerClassNode) receiver).isAnonymous() && methods.size() == 1 && args != null && "<init>".equals(name)) {
MethodNode constructor = methods.get(0);
if (constructor.getParameters().length == args.length) {
return methods;
}
}
if (receiver.equals(CLASS_Type) && receiver.getGenericsTypes() != null) {
List<MethodNode> result = findMethod(receiver.getGenericsTypes()[0].getType(), name, args);
if (!result.isEmpty())
return result;
}
if (ClassHelper.GSTRING_TYPE.equals(receiver))
return findMethod(ClassHelper.STRING_TYPE, name, args);
if (isBeingCompiled(receiver)) {
chosen = findMethod(GROOVY_OBJECT_TYPE, name, args);
if (!chosen.isEmpty())
return chosen;
}
return EMPTY_METHODNODE_LIST;
}
use of org.codehaus.groovy.ast.MethodNode in project groovy-core by groovy.
the class TraitTypeCheckingExtension method handleMissingMethod.
@Override
public List<MethodNode> handleMissingMethod(final ClassNode receiver, final String name, final ArgumentListExpression argumentList, final ClassNode[] argumentTypes, final MethodCall call) {
String[] decomposed = Traits.decomposeSuperCallName(name);
if (decomposed != null) {
return convertToDynamicCall(call, receiver, decomposed, argumentTypes);
}
if (call instanceof MethodCallExpression) {
MethodCallExpression mce = (MethodCallExpression) call;
if (mce.getReceiver() instanceof VariableExpression) {
VariableExpression var = (VariableExpression) mce.getReceiver();
// GROOVY-7322
// static method call in trait?
ClassNode type = null;
if (isStaticTraitReceiver(receiver, var)) {
type = receiver.getGenericsTypes()[0].getType();
} else if (isThisTraitReceiver(var)) {
type = receiver;
}
if (type != null && Traits.isTrait(type)) {
ClassNode helper = Traits.findHelper(type);
Parameter[] params = new Parameter[argumentTypes.length + 1];
params[0] = new Parameter(ClassHelper.CLASS_Type.getPlainNodeReference(), "staticSelf");
for (int i = 1; i < params.length; i++) {
params[i] = new Parameter(argumentTypes[i - 1], "p" + i);
}
MethodNode method = helper.getDeclaredMethod(name, params);
if (method != null) {
return Collections.singletonList(makeDynamic(call, method.getReturnType()));
}
}
}
ClassNode dynamic = mce.getNodeMetaData(TraitASTTransformation.DO_DYNAMIC);
if (dynamic != null) {
return Collections.singletonList(makeDynamic(call, dynamic));
}
}
return NOTFOUND;
}
Aggregations