in src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java [5168:5294]
protected ClassNode getType(final ASTNode node) {
ClassNode type = node.getNodeMetaData(INFERRED_TYPE);
if (type != null) {
return type;
}
if (node instanceof ClassExpression) {
type = ((ClassExpression) node).getType();
return makeClassSafe0(CLASS_Type, new GenericsType(type));
}
if (node instanceof VariableExpression) {
VariableExpression vexp = (VariableExpression) node;
type = isTraitSelf(vexp);
if (type != null) return makeSelf(type);
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;
// 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
if (type == null && temporaryTypesForExpression == null) {
type = getTypeFromClosureArguments(parameter);
}
if (type != null) {
storeType(vexp, type);
return type;
}
return getType((Parameter) variable);
}
return vexp.getOriginType();
}
if (node instanceof Parameter || node instanceof FieldNode || node instanceof PropertyNode) {
return ((Variable) node).getOriginType();
}
if (node instanceof MethodNode) {
type = ((MethodNode) node).getReturnType();
return Optional.ofNullable(getInferredReturnType(node)).orElse(type);
}
if (node instanceof MethodCall) {
if (node instanceof ConstructorCallExpression) {
return ((ConstructorCallExpression) node).getType();
}
MethodNode target = node.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
if (target != null) {
return getType(target);
}
}
if (node instanceof ClosureExpression) {
type = CLOSURE_TYPE.getPlainNodeReference();
ClassNode returnType = getInferredReturnType(node);
if (returnType != null) {
type.setGenericsTypes(new GenericsType[]{
new GenericsType(wrapTypeIfNecessary(returnType))
});
}
Parameter[] parameters = ((ClosureExpression) node).getParameters();
int nParameters = parameters == null ? 0
: parameters.length == 0 ? -1 : parameters.length;
type.putNodeMetaData(CLOSURE_ARGUMENTS, nParameters);
return type;
}
if (node instanceof ListExpression) {
return inferListExpressionType((ListExpression) node);
}
if (node instanceof MapExpression) {
return inferMapExpressionType((MapExpression) node);
}
if (node instanceof RangeExpression) {
RangeExpression re = (RangeExpression) node;
ClassNode fromType = getType(re.getFrom());
ClassNode toType = getType(re.getTo());
if (fromType.equals(toType)) {
type = wrapTypeIfNecessary(fromType);
} else {
type = wrapTypeIfNecessary(lowestUpperBound(fromType, toType));
}
return makeClassSafe0(RANGE_TYPE, new GenericsType(type));
}
if (node instanceof SpreadExpression) {
type = getType(((SpreadExpression) node).getExpression());
type = inferComponentType(type, null); // for list literal
if (type == null) // GROOVY-11572: not an iterable
type = UNKNOWN_PARAMETER_TYPE;
return type;
}
if (node instanceof UnaryPlusExpression) {
return getType(((UnaryPlusExpression) node).getExpression());
}
if (node instanceof UnaryMinusExpression) {
return getType(((UnaryMinusExpression) node).getExpression());
}
if (node instanceof BitwiseNegationExpression) {
return getType(((BitwiseNegationExpression) node).getExpression());
}
return ((Expression) node).getType();
}