use of org.codehaus.groovy.ast.ClassNode in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method visitTernaryExpression.
@Override
public void visitTernaryExpression(final TernaryExpression expression) {
Map<VariableExpression, List<ClassNode>> oldTracker = pushAssignmentTracking();
// create a new temporary element in the if-then-else type info
typeCheckingContext.pushTemporaryTypeInfo();
expression.getBooleanExpression().visit(this);
Expression trueExpression = expression.getTrueExpression();
Expression falseExpression = expression.getFalseExpression();
trueExpression.visit(this);
// pop if-then-else temporary type info
typeCheckingContext.popTemporaryTypeInfo();
falseExpression.visit(this);
ClassNode resultType;
if (isNullConstant(trueExpression) || isNullConstant(falseExpression)) {
BinaryExpression enclosingBinaryExpression = typeCheckingContext.getEnclosingBinaryExpression();
if (enclosingBinaryExpression != null && enclosingBinaryExpression.getRightExpression() == expression) {
resultType = getType(enclosingBinaryExpression.getLeftExpression());
} else if (isNullConstant(trueExpression) && isNullConstant(falseExpression)) {
resultType = OBJECT_TYPE;
} else if (isNullConstant(trueExpression)) {
resultType = wrapTypeIfNecessary(getType(falseExpression));
} else {
resultType = wrapTypeIfNecessary(getType(trueExpression));
}
} else {
// store type information
final ClassNode typeOfTrue = getType(trueExpression);
final ClassNode typeOfFalse = getType(falseExpression);
resultType = lowestUpperBound(typeOfTrue, typeOfFalse);
}
storeType(expression, resultType);
popAssignmentTracking(oldTracker);
}
use of org.codehaus.groovy.ast.ClassNode 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.ClassNode in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method getDeclaringClass.
private static ClassNode getDeclaringClass(MethodNode method, Expression arguments) {
ClassNode declaringClass = method.getDeclaringClass();
// correcting declaring class for extension methods:
if (arguments instanceof ArgumentListExpression) {
ArgumentListExpression al = (ArgumentListExpression) arguments;
List<Expression> list = al.getExpressions();
if (list.size() == 0)
return declaringClass;
Expression exp = list.get(0);
ClassNode cn = exp.getNodeMetaData(ExtensionMethodDeclaringClass.class);
if (cn != null)
return cn;
}
return declaringClass;
}
use of org.codehaus.groovy.ast.ClassNode in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method storeTypeForThis.
private boolean storeTypeForThis(VariableExpression vexp) {
if (vexp == VariableExpression.THIS_EXPRESSION)
return true;
if (!vexp.isThisExpression())
return false;
ClassNode enclosingClassNode = typeCheckingContext.getEnclosingClassNode();
storeType(vexp, makeType(enclosingClassNode, typeCheckingContext.isInStaticContext));
return true;
}
use of org.codehaus.groovy.ast.ClassNode in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method tryVariableExpressionAsProperty.
private boolean tryVariableExpressionAsProperty(final VariableExpression vexp, final String dynName) {
VariableExpression implicitThis = new VariableExpression("this");
PropertyExpression pe = new PropertyExpression(implicitThis, dynName);
pe.setImplicitThis(true);
if (visitPropertyExpressionSilent(pe, vexp)) {
ClassNode previousIt = vexp.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
vexp.copyNodeMetaData(implicitThis);
vexp.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, previousIt);
storeType(vexp, getType(pe));
Object val = pe.getNodeMetaData(StaticTypesMarker.READONLY_PROPERTY);
if (val != null)
vexp.putNodeMetaData(StaticTypesMarker.READONLY_PROPERTY, val);
val = pe.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
if (val != null)
vexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, val);
return true;
}
return false;
}
Aggregations