if (expression instanceof BinaryExpression) {
Expression left = ((BinaryExpression) expression).getLeftExpression();
if (left instanceof VariableExpression) {
// should always be the case
// this should always be the case, but adding a test is safer
Variable target = findTargetVariable((VariableExpression) left);
if (target instanceof VariableExpression) {
VariableExpression var = (VariableExpression) target;
List<ClassNode> classNodes = typeCheckingContext.closureSharedVariablesAssignmentTypes.get(var);
if (classNodes != null && classNodes.size() > 1) {
ClassNode lub = lowestUpperBound(classNodes);
String message = getOperationName(((BinaryExpression) expression).getOperation().getType());
if (message!=null) {
List<MethodNode> method = findMethod(lub, message, getType(((BinaryExpression) expression).getRightExpression()));
if (method.isEmpty()) {
addStaticTypeError("A closure shared variable [" + target.getName() + "] has been assigned with various types and the method" +
" [" + toMethodParametersString(message, getType(((BinaryExpression) expression).getRightExpression())) + "]" +
" does not exist in the lowest upper bound of those types: [" +
lub.toString(false) + "]. In general, this is a bad practice (variable reuse) because the compiler cannot" +
" determine safely what is the type of the variable at the moment of the call in a multithreaded context.", expression);
}
}
}
}
}
} else if (expression instanceof MethodCallExpression) {
MethodCallExpression call = (MethodCallExpression) expression;
Expression objectExpression = call.getObjectExpression();
if (objectExpression instanceof VariableExpression) {
// this should always be the case, but adding a test is safer
Variable target = findTargetVariable((VariableExpression) objectExpression);
if (target instanceof VariableExpression) {
VariableExpression var = (VariableExpression) target;
List<ClassNode> classNodes = typeCheckingContext.closureSharedVariablesAssignmentTypes.get(var);
if (classNodes != null && classNodes.size() > 1) {
ClassNode lub = lowestUpperBound(classNodes);
MethodNode methodNode = (MethodNode) call.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
// we must check that such a method exists on the LUB
Parameter[] parameters = methodNode.getParameters();
ClassNode[] params = extractTypesFromParameters(parameters);
ClassNode[] argTypes = (ClassNode[]) wrapper.getData();
List<MethodNode> method = findMethod(lub, methodNode.getName(), argTypes);
if (method.size() != 1) {
addStaticTypeError("A closure shared variable [" + target.getName() + "] has been assigned with various types and the method" +
" [" + toMethodParametersString(methodNode.getName(), params) + "]" +
" does not exist in the lowest upper bound of those types: [" +
lub.toString(false) + "]. In general, this is a bad practice (variable reuse) because the compiler cannot" +
" determine safely what is the type of the variable at the moment of the call in a multithreaded context.", call);
}