Skip to content

Commit

Permalink
Implemented type analysis support for comparison chaining.
Browse files Browse the repository at this point in the history
  • Loading branch information
msfterictraut committed Sep 22, 2019
1 parent a109484 commit 57ca2da
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 2 deletions.
16 changes: 14 additions & 2 deletions server/src/analyzer/expressionEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2750,7 +2750,20 @@ export class ExpressionEvaluator {
}

private _getTypeFromBinaryExpression(node: BinaryExpressionNode): TypeResult {
let leftType = this.getType(node.leftExpression);
let leftExpression = node.leftExpression;

// If this is a comparison and the left expression is also a comparison,
// we need to change the behavior to accommodate python's "chained
// comparisons" feature.
if (comparisonOperatorMap[node.operator]) {
if (node.leftExpression.nodeType === ParseNodeType.BinaryOperation &&
comparisonOperatorMap[node.leftExpression.operator]) {

leftExpression = node.leftExpression.rightExpression;
}
}

let leftType = this.getType(leftExpression);

// Is this an AND operator? If so, we can assume that the
// rightExpression won't be evaluated at runtime unless the
Expand Down Expand Up @@ -2813,7 +2826,6 @@ export class ExpressionEvaluator {
};

let type: Type | undefined;

const leftType = this.getType(node.leftExpression);
const rightType = this.getType(node.rightExpression);

Expand Down
23 changes: 23 additions & 0 deletions server/src/tests/samples/operators2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# This sample tests the type checker's handling of chained
# comparison operators.

from datetime import datetime

def requires_bool(val: bool):
pass

date1 = datetime.now()
date2 = datetime.now()
date3 = datetime.now()

foo1 = date1 < date2 <= date3
requires_bool(foo1)

int1 = 3
foo2 = 2 < int1 < 5
requires_bool(foo2)

# This should generate an error because
# int and datetime cannot be compared.
foo3 = date1 < date2 < 3

6 changes: 6 additions & 0 deletions server/src/tests/typeAnalyzer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ test('Operators1', () => {
validateResults(analysisResults, 3);
});

test('Operators2', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['operators2.py']);

validateResults(analysisResults, 1);
});

test('Optional1', () => {
const configOptions = new ConfigOptions('.');

Expand Down

0 comments on commit 57ca2da

Please sign in to comment.