use of org.codehaus.groovy.ast.expr.MethodCall in project groovy by apache.
the class StaticTypeCheckingVisitor method getType.
protected ClassNode getType(final ASTNode exp) {
ClassNode cn = exp.getNodeMetaData(INFERRED_TYPE);
if (cn != null) {
return cn;
}
if (exp instanceof ClassExpression) {
ClassNode node = CLASS_Type.getPlainNodeReference();
node.setGenericsTypes(new GenericsType[] { new GenericsType(((ClassExpression) exp).getType()) });
return node;
}
if (exp instanceof VariableExpression) {
VariableExpression vexp = (VariableExpression) exp;
ClassNode selfTrait = isTraitSelf(vexp);
if (selfTrait != null)
return makeSelf(selfTrait);
if (vexp.isThisExpression())
return makeThis();
if (vexp.isSuperExpression())
return makeSuper();
Variable variable = vexp.getAccessedVariable();
if (variable instanceof FieldNode) {
FieldNode fieldNode = (FieldNode) variable;
ClassNode fieldType = fieldNode.getOriginType();
if (!fieldNode.isStatic() && GenericsUtils.hasUnresolvedGenerics(fieldType)) {
ClassNode declType = fieldNode.getDeclaringClass(), thisType = typeCheckingContext.getEnclosingClassNode();
fieldType = resolveGenericsWithContext(extractPlaceHolders(thisType, declType), fieldType);
}
return fieldType;
}
if (variable != vexp && variable instanceof VariableExpression) {
return getType((VariableExpression) variable);
}
if (variable instanceof Parameter) {
Parameter parameter = (Parameter) variable;
ClassNode type = null;
// check if param part of control structure - but not if inside instanceof
List<ClassNode> temporaryTypesForExpression = getTemporaryTypesForExpression(vexp);
if (temporaryTypesForExpression == null || temporaryTypesForExpression.isEmpty()) {
type = typeCheckingContext.controlStructureVariables.get(parameter);
}
// now check for closure override
TypeCheckingContext.EnclosingClosure enclosingClosure = typeCheckingContext.getEnclosingClosure();
if (type == null && enclosingClosure != null && temporaryTypesForExpression == null) {
type = getTypeFromClosureArguments(parameter, enclosingClosure);
}
if (type != null) {
storeType(vexp, type);
return type;
}
return getType((Parameter) variable);
}
return vexp.getOriginType();
}
if (exp instanceof ListExpression) {
return inferListExpressionType((ListExpression) exp);
}
if (exp instanceof MapExpression) {
return inferMapExpressionType((MapExpression) exp);
}
if (exp instanceof ConstructorCallExpression) {
return ((ConstructorCallExpression) exp).getType();
}
if (exp instanceof MethodNode) {
if ((exp == GET_DELEGATE || exp == GET_OWNER || exp == GET_THISOBJECT) && typeCheckingContext.getEnclosingClosure() != null) {
return typeCheckingContext.getEnclosingClassNode();
}
ClassNode ret = getInferredReturnType(exp);
return ret != null ? ret : ((MethodNode) exp).getReturnType();
}
if (exp instanceof FieldNode || exp instanceof PropertyNode) {
return ((Variable) exp).getOriginType();
}
if (exp instanceof RangeExpression) {
ClassNode plain = RANGE_TYPE.getPlainNodeReference();
RangeExpression re = (RangeExpression) exp;
ClassNode fromType = getType(re.getFrom());
ClassNode toType = getType(re.getTo());
if (fromType.equals(toType)) {
plain.setGenericsTypes(new GenericsType[] { new GenericsType(wrapTypeIfNecessary(fromType)) });
} else {
plain.setGenericsTypes(new GenericsType[] { new GenericsType(wrapTypeIfNecessary(lowestUpperBound(fromType, toType))) });
}
return plain;
}
if (exp instanceof UnaryPlusExpression) {
return getType(((UnaryPlusExpression) exp).getExpression());
}
if (exp instanceof UnaryMinusExpression) {
return getType(((UnaryMinusExpression) exp).getExpression());
}
if (exp instanceof BitwiseNegationExpression) {
return getType(((BitwiseNegationExpression) exp).getExpression());
}
if (exp instanceof Parameter) {
return ((Parameter) exp).getOriginType();
}
if (exp instanceof ClosureExpression) {
ClassNode type = CLOSURE_TYPE.getPlainNodeReference();
ClassNode returnType = getInferredReturnType(exp);
if (returnType != null) {
type.setGenericsTypes(new GenericsType[] { new GenericsType(wrapTypeIfNecessary(returnType)) });
}
Parameter[] parameters = ((ClosureExpression) exp).getParameters();
int nParameters = parameters == null ? 0 : parameters.length == 0 ? -1 : parameters.length;
type.putNodeMetaData(CLOSURE_ARGUMENTS, nParameters);
return type;
} else if (exp instanceof MethodCall) {
MethodNode target = exp.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
if (target != null) {
return getType(target);
}
}
return ((Expression) exp).getType();
}
use of org.codehaus.groovy.ast.expr.MethodCall in project groovy by apache.
the class StaticTypeCheckingVisitor method disambiguateMethods.
private List<MethodNode> disambiguateMethods(List<MethodNode> methods, final ClassNode receiver, final ClassNode[] argTypes, final Expression call) {
if (methods.size() > 1 && receiver != null && argTypes != null) {
List<MethodNode> filteredWithGenerics = new LinkedList<>();
for (MethodNode methodNode : methods) {
if (typeCheckMethodsWithGenerics(receiver, argTypes, methodNode)) {
if ((methodNode.getModifiers() & Opcodes.ACC_BRIDGE) == 0) {
filteredWithGenerics.add(methodNode);
}
}
}
if (filteredWithGenerics.size() == 1) {
return filteredWithGenerics;
}
methods = extension.handleAmbiguousMethods(methods, call);
}
if (methods.size() > 1) {
if (call instanceof MethodCall) {
List<MethodNode> methodNodeList = new LinkedList<>();
String methodName = ((MethodCall) call).getMethodAsString();
for (MethodNode methodNode : methods) {
if (!methodNode.getName().equals(methodName)) {
continue;
}
methodNodeList.add(methodNode);
}
methods = methodNodeList;
}
}
return methods;
}
use of org.codehaus.groovy.ast.expr.MethodCall in project groovy by apache.
the class StaticTypeCheckingVisitor method typeCheckMultipleAssignmentAndContinue.
private boolean typeCheckMultipleAssignmentAndContinue(final Expression leftExpression, Expression rightExpression) {
if (rightExpression instanceof VariableExpression || rightExpression instanceof PropertyExpression || rightExpression instanceof MethodCall) {
ClassNode inferredType = Optional.ofNullable(getType(rightExpression)).orElseGet(rightExpression::getType);
GenericsType[] genericsTypes = inferredType.getGenericsTypes();
ListExpression listExpression = new ListExpression();
listExpression.setSourcePosition(rightExpression);
// convert Tuple[1-16] bearing expressions to mock list for checking
for (int n = TUPLE_TYPES.indexOf(inferredType), i = 0; i < n; i += 1) {
ClassNode type = (genericsTypes != null ? genericsTypes[i].getType() : OBJECT_TYPE);
listExpression.addExpression(varX("v" + (i + 1), type));
}
if (!listExpression.getExpressions().isEmpty()) {
rightExpression = listExpression;
}
}
if (!(rightExpression instanceof ListExpression)) {
addStaticTypeError("Multiple assignments without list or tuple on the right-hand side are unsupported in static type checking mode", rightExpression);
return false;
}
TupleExpression tuple = (TupleExpression) leftExpression;
ListExpression values = (ListExpression) rightExpression;
List<Expression> tupleExpressions = tuple.getExpressions();
List<Expression> valueExpressions = values.getExpressions();
if (tupleExpressions.size() > valueExpressions.size()) {
addStaticTypeError("Incorrect number of values. Expected:" + tupleExpressions.size() + " Was:" + valueExpressions.size(), values);
return false;
}
for (int i = 0, n = tupleExpressions.size(); i < n; i += 1) {
ClassNode valueType = getType(valueExpressions.get(i));
ClassNode targetType = getType(tupleExpressions.get(i));
if (!isAssignableTo(valueType, targetType)) {
addStaticTypeError("Cannot assign value of type " + prettyPrintType(valueType) + " to variable of type " + prettyPrintType(targetType), rightExpression);
return false;
}
storeType(tupleExpressions.get(i), valueType);
}
return true;
}
Aggregations