Reduce number of negations in some cases.

This commit is contained in:
Alex Eyers-Taylor
2025-01-09 16:46:58 +00:00
parent 3437210d32
commit 34ab6b3919
2 changed files with 57 additions and 46 deletions

View File

@@ -44,6 +44,8 @@ class UsingWhileAfterWhile extends WhileStmt {
} }
} }
/** /**
* Using arithmetic in a condition. * Using arithmetic in a condition.
*/ */
@@ -55,15 +57,15 @@ class UsingArithmeticInComparison extends BinaryArithmeticOperation {
*/ */
UsingArithmeticInComparison() { UsingArithmeticInComparison() {
this.getParent*() instanceof IfStmt and this.getParent*() instanceof IfStmt and
not this.getAChild*().isConstant() and not (this.getAChild*().isConstant() or
not this.getParent*() instanceof Call and this.getParent*() instanceof Call or
not this.getParent*() instanceof AssignExpr and this.getParent*() instanceof AssignExpr or
not this.getParent*() instanceof ArrayExpr and this.getParent*() instanceof ArrayExpr or
not this.getParent*() instanceof RemExpr and this.getParent*() instanceof RemExpr or
not this.getParent*() instanceof AssignBitwiseOperation and this.getParent*() instanceof AssignBitwiseOperation or
not this.getParent*() instanceof AssignArithmeticOperation and this.getParent*() instanceof AssignArithmeticOperation or
not this.getParent*() instanceof EqualityOperation and this.getParent*() instanceof EqualityOperation or
not this.getParent*() instanceof RelationalOperation this.getParent*() instanceof RelationalOperation)
} }
/** Holds when the expression is inside the loop body. */ /** Holds when the expression is inside the loop body. */

View File

@@ -13,6 +13,39 @@ predicate duplicateChildren(Element e, int i) {
not e instanceof Constructor not e instanceof Constructor
} }
predicate allowableGap(Element e, int i) {
// Annotations are child 0 upwards, 'implements' are -2 downwards,
// and there may or may not be an 'extends' for child -1.
e instanceof ClassOrInterface and i = -1
or
// A class instance creation expression has the type as child -3,
// may or may not have a qualifier as child -2, and will never have
// a child -1.
e instanceof ClassInstanceExpr and i = [-2, -1]
or
// Type access have annotations from -2 down, and type
// arguments from 0 up, but may or may not have a qualifier
// at -1.
e instanceof TypeAccess and i = -1
or
// Try statements have their 'finally' clause as child 2,
// and that may or may not exist.
e instanceof TryStmt and i = -2
or
// For statements may or may not declare a new variable (child 0), or
// have a condition (child 1).
e instanceof ForStmt and i = [0, 1]
or
// Pattern case statements legitimately have a TypeAccess (-2) and a pattern (0) but not a rule (-1)
i = -1 and e instanceof PatternCase and not e.(PatternCase).isRule()
or
// Pattern case statements can have a gap at -3 when they have more than one pattern but no guard.
i = -3 and count(e.(PatternCase).getAPattern()) > 1 and not exists(e.(PatternCase).getGuard())
or
// Instanceof with a record pattern is not expected to have a type access in position 1
i = 1 and e.(InstanceOfExpr).getPattern() instanceof RecordPatternExpr
}
predicate gapInChildren(Element e, int i) { predicate gapInChildren(Element e, int i) {
exists(int left, int right | exists(int left, int right |
left = min(int l | exists(nthChildOf(e, l))) and left = min(int l | exists(nthChildOf(e, l))) and
@@ -20,48 +53,24 @@ predicate gapInChildren(Element e, int i) {
i in [left .. right] and i in [left .. right] and
not exists(nthChildOf(e, i)) not exists(nthChildOf(e, i))
) and ) and
// Annotations are child 0 upwards, 'implements' are -2 downwards, not allowableGap(e, i) and
// and there may or may not be an 'extends' for child -1. not (
not (e instanceof ClassOrInterface and i = -1) and // Pattern case statements may have some missing type accesses, depending on the nature of the direct child
// A class instance creation expression has the type as child -3, (i = -2 or i < -4) and
// may or may not have a qualifier as child -2, and will never have e instanceof PatternCase
// a child -1. ) and
not (e instanceof ClassInstanceExpr and i = [-2, -1]) and // RecordPatternExpr extracts type-accesses only for its LocalVariableDeclExpr children
// Type access have annotations from -2 down, and type not (i < 0 and e instanceof RecordPatternExpr) and
// arguments from 0 up, but may or may not have a qualifier
// at -1.
not (e instanceof TypeAccess and i = -1) and
// Try statements have their 'finally' clause as child 2,
// and that may or may not exist.
not (e instanceof TryStmt and i = -2) and
// For statements may or may not declare a new variable (child 0), or
// have a condition (child 1).
not (e instanceof ForStmt and i = [0, 1]) and
// TODO: Clarify situation with Kotlin and MethodCall.
// -1 can be skipped (type arguments from -2 down, no qualifier at -1,
// then arguments from 0).
// Can we also skip arguments, e.g. due to defaults for parameters?
not (e instanceof MethodCall and e.getFile().isKotlinSourceFile()) and
// Kotlin-extracted annotations can have missing children where a default // Kotlin-extracted annotations can have missing children where a default
// value should be, because kotlinc doesn't load annotation defaults and we // value should be, because kotlinc doesn't load annotation defaults and we
// want to leave a space for another extractor to fill in the default if it // want to leave a space for another extractor to fill in the default if it
// is able. // is able.
not e instanceof Annotation and not e instanceof Annotation and
// Pattern case statements legitimately have a TypeAccess (-2) and a pattern (0) but not a rule (-1) // TODO: Clarify situation with Kotlin and MethodCall.
not (i = -1 and e instanceof PatternCase and not e.(PatternCase).isRule()) and // -1 can be skipped (type arguments from -2 down, no qualifier at -1,
// Pattern case statements can have a gap at -3 when they have more than one pattern but no guard. // then arguments from 0).
not ( // Can we also skip arguments, e.g. due to defaults for parameters?
i = -3 and count(e.(PatternCase).getAPattern()) > 1 and not exists(e.(PatternCase).getGuard()) not (e instanceof MethodCall and e.getFile().isKotlinSourceFile())
) and
// Pattern case statements may have some missing type accesses, depending on the nature of the direct child
not (
(i = -2 or i < -4) and
e instanceof PatternCase
) and
// Instanceof with a record pattern is not expected to have a type access in position 1
not (i = 1 and e.(InstanceOfExpr).getPattern() instanceof RecordPatternExpr) and
// RecordPatternExpr extracts type-accesses only for its LocalVariableDeclExpr children
not (i < 0 and e instanceof RecordPatternExpr)
} }
predicate lateFirstChild(Element e, int i) { predicate lateFirstChild(Element e, int i) {