BinaryExpressionImpl extends PyTree implements BinaryExpression, HasTypeDependencies { @Override public InferredType type() { if (is(Kind.AND, Kind.OR)) { return InferredTypes.or(leftOperand.type(), rightOperand.type()); } if (is(Kind.PLUS)) { InferredType leftType = leftOperand.type(); InferredType rightType = rightOperand.type(); if (leftType.equals(INT) && rightType.equals(INT)) { return INT; } if (leftType.equals(STR) && rightType.equals(STR)) { return STR; } if (shouldReturnDeclaredInt(leftType, rightType)) { return DECL_INT; } if (shouldReturnDeclaredStr(leftType, rightType)) { return DECL_STR; } } return InferredTypes.anyType(); } BinaryExpressionImpl(Expression leftOperand, Token operator, Expression rightOperand); @Override Expression leftOperand(); @Override Token operator(); @Override Expression rightOperand(); @Override void accept(TreeVisitor visitor); @Override Kind getKind(); @Override List<Tree> computeChildren(); @Override InferredType type(); @Override List<Expression> typeDependencies();  }
@Test public void type() { assertThat(lastExpression("42 + 43").type()).isEqualTo(INT); assertThat(lastExpression("'foo' + 'bar'").type()).isEqualTo(STR); assertThat(lastExpression("True + False").type()).isEqualTo(InferredTypes.anyType()); assertThat(lastExpression("42 + ''").type()).isEqualTo(InferredTypes.anyType()); assertThat(lastExpression("'' + 42").type()).isEqualTo(InferredTypes.anyType()); assertThat(lastExpression("'' assertThat(lastExpression("def f(x: int, y: int): x + y").type()).isEqualTo(DECL_INT); assertThat(lastExpression("def f(x: int, y: int): x + 42").type()).isEqualTo(DECL_INT); assertThat(lastExpression("def f(x: int, y: int): 42 + y").type()).isEqualTo(DECL_INT); assertThat(lastExpression("def f(x: str, y: str): x + y").type()).isEqualTo(DECL_STR); assertThat(lastExpression("def f(x: str, y: str): x + 'foo'").type()).isEqualTo(DECL_STR); assertThat(lastExpression("def f(x: str, y: str): 'foo' + y").type()).isEqualTo(DECL_STR); assertThat(lastExpression("def f(x: str, y: int): x + y").type()).isEqualTo(anyType()); assertThat(lastExpression("def f(x: int, y: str): x + y").type()).isEqualTo(anyType()); assertThat(lastExpression("def f(x: int, y: str): x + 'foo'").type()).isEqualTo(anyType()); }
@Test public void logical_expressions() { assertThat(lastExpression("42 or 43").type()).isEqualTo(INT); assertThat(lastExpression("42 and 43").type()).isEqualTo(INT); assertThat(lastExpression("42 or ''").type()).isEqualTo(or(INT, STR)); assertThat(lastExpression("42 or xxx").type()).isEqualTo(anyType()); assertThat(lastExpression("42 or True or ''").type()).isEqualTo(or(or(INT, STR), BOOL)); assertThat(lastExpression("def f(x: int, y: int): x or y").type()).isEqualTo(DECL_INT); assertThat(lastExpression("def f(x: int, y: int): x and y").type()).isEqualTo(DECL_INT); assertThat(lastExpression("def f(x: int, y: str): x or y").type()).isEqualTo(or(DECL_INT, DECL_STR)); assertThat(lastExpression("def f(x: int, y): x or y").type()).isEqualTo(anyType()); assertThat(lastExpression("def f(x: int, y: bool, z: str): x or y or z").type()).isEqualTo(or(or(DECL_INT, DECL_STR), DECL_BOOL)); }
@Test public void long_sequence_binary_expressions() { InferredType type = lastExpression( "'a' + 'b' + 'c' + 'd' + 'e' + 'f' + 'g' + 'a' + 'b' + 'c' + 'd' + 'e' + 'f' + 'g' + 'a' + 'b' + 'c' + 'd' + 'e' +" + " 'f' + 'g' + 'a' + 'b' + 'c' + 'd' + 'e' + 'f' + 'g' + 'a' + 'b' + 'c' + 'd' + 'e' + 'f' + 'g' + 'a' + 'b' + 'c' + 'd' + 'e' + 'f' + 'g'" ).type(); assertThat(type.canOnlyBe("str")).isTrue(); }