66import csharp
77
88//#################### PREDICATES ####################
9- Stmt firstStmt ( ForeachStmt fes ) {
9+ private Stmt firstStmt ( ForeachStmt fes ) {
1010 if fes .getBody ( ) instanceof BlockStmt
1111 then result = fes .getBody ( ) .( BlockStmt ) .getStmt ( 0 )
1212 else result = fes .getBody ( )
1313}
1414
15+ private int numStmts ( ForeachStmt fes ) {
16+ if fes .getBody ( ) instanceof BlockStmt
17+ then result = count ( fes .getBody ( ) .( BlockStmt ) .getAStmt ( ) )
18+ else result = 1
19+ }
20+
21+ /** Holds if the type's qualified name is "System.Linq.Enumerable" */
1522predicate isEnumerableType ( ValueOrRefType t ) { t .hasQualifiedName ( "System.Linq.Enumerable" ) }
1623
24+ /** Holds if the type's qualified name starts with "System.Collections.Generic.IEnumerable" */
1725predicate isIEnumerableType ( ValueOrRefType t ) {
1826 t .getQualifiedName ( ) .matches ( "System.Collections.Generic.IEnumerable%" )
1927}
2028
29+ /**
30+ * Holds if `ForeachStmt` could be converted to a `.All()` call. That is,
31+ * the `ForeachStmt` contains a single `if` with a condition that accesses
32+ * the loop variable and with a body that assigns `false` to a variable and
33+ * `break`s out of the `foreach`.
34+ */
2135predicate missedAllOpportunity ( ForeachStmt fes ) {
2236 exists ( IfStmt is |
2337 // The loop contains an if statement with no else case, and nothing else.
@@ -36,6 +50,11 @@ predicate missedAllOpportunity(ForeachStmt fes) {
3650 )
3751}
3852
53+ /**
54+ * Holds if `ForeachStmt` could be converted to a `.Cast()` call. That is, the
55+ * loop variable is accessed only in the first statement of the block, and the
56+ * access is a cast. The first statement needs to be a `LocalVariableDeclStmt`.
57+ */
3958predicate missedCastOpportunity ( ForeachStmt fes , LocalVariableDeclStmt s ) {
4059 s = firstStmt ( fes ) and
4160 forex ( VariableAccess va | va = fes .getVariable ( ) .getAnAccess ( ) |
@@ -47,6 +66,12 @@ predicate missedCastOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) {
4766 )
4867}
4968
69+ /**
70+ * Holds if `ForeachStmt` could be converted to an `.OfType()` call. That is, the
71+ * loop variable is accessed only in the first statement of the block, and the
72+ * access is a cast with the `as` operator. The first statement needs to be a
73+ * `LocalVariableDeclStmt`.
74+ */
5075predicate missedOfTypeOpportunity ( ForeachStmt fes , LocalVariableDeclStmt s ) {
5176 s = firstStmt ( fes ) and
5277 forex ( VariableAccess va | va = fes .getVariable ( ) .getAnAccess ( ) |
@@ -58,6 +83,11 @@ predicate missedOfTypeOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) {
5883 )
5984}
6085
86+ /**
87+ * Holds if `ForeachStmt` could be converted to a `.Select()` call. That is, the
88+ * loop variable is accessed only in the first statement of the block, and the
89+ * access is not a cast. The first statement needs to be a `LocalVariableDeclStmt`.
90+ */
6191predicate missedSelectOpportunity ( ForeachStmt fes , LocalVariableDeclStmt s ) {
6292 s = firstStmt ( fes ) and
6393 forex ( VariableAccess va | va = fes .getVariable ( ) .getAnAccess ( ) |
@@ -66,6 +96,12 @@ predicate missedSelectOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) {
6696 not s .getAVariableDeclExpr ( ) .getInitializer ( ) instanceof Cast
6797}
6898
99+ /**
100+ * Holds if `ForeachStmt` could be converted to a `.Where()` call. That is, first
101+ * statement of the loop is an `if`, which accesses the loop variable, and the body
102+ * of the `if` is either a `continue` or there's nothing else in the loop than the
103+ * `if`.
104+ */
69105predicate missedWhereOpportunity ( ForeachStmt fes , IfStmt is ) {
70106 // The very first thing the foreach loop does is test its iteration variable.
71107 is = firstStmt ( fes ) and
@@ -82,12 +118,6 @@ predicate missedWhereOpportunity(ForeachStmt fes, IfStmt is) {
82118 )
83119}
84120
85- int numStmts ( ForeachStmt fes ) {
86- if fes .getBody ( ) instanceof BlockStmt
87- then result = count ( fes .getBody ( ) .( BlockStmt ) .getAStmt ( ) )
88- else result = 1
89- }
90-
91121//#################### CLASSES ####################
92122/** A LINQ Any(...) call. */
93123class AnyCall extends MethodCall {
0 commit comments