mirror of
https://github.com/github/codeql.git
synced 2026-06-16 02:11:09 +02:00
Compare commits
2 Commits
main
...
copilot/ch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f658bc9b39 | ||
|
|
8cb4b9b118 |
@@ -442,31 +442,4 @@ namespace My.Qltest
|
||||
|
||||
static void Sink(object o) { }
|
||||
}
|
||||
|
||||
// Test operator overloads
|
||||
public class N
|
||||
{
|
||||
public void operator +=(N y) => throw null;
|
||||
|
||||
public void operator checked +=(N y) => throw null;
|
||||
|
||||
public void M1(N n)
|
||||
{
|
||||
var n0 = new N();
|
||||
n += n0;
|
||||
Sink(n);
|
||||
}
|
||||
|
||||
public void M2(N n)
|
||||
{
|
||||
var n0 = new N();
|
||||
checked
|
||||
{
|
||||
n += n0;
|
||||
}
|
||||
Sink(n);
|
||||
}
|
||||
|
||||
static void Sink(object o) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,16 +32,14 @@ models
|
||||
| 31 | Summary: My.Qltest; Library; false; GetValue; (); ; Argument[this].SyntheticField[X]; ReturnValue; value; dfc-generated |
|
||||
| 32 | Summary: My.Qltest; Library; false; MixedFlowArgs; (System.Object,System.Object); ; Argument[1]; ReturnValue; value; manual |
|
||||
| 33 | Summary: My.Qltest; Library; false; SetValue; (System.Object); ; Argument[0]; Argument[this].SyntheticField[X]; value; dfc-generated |
|
||||
| 34 | Summary: My.Qltest; N; false; op_AdditionAssignment; (My.Qltest.N); ; Argument[0]; Argument[this]; taint; manual |
|
||||
| 35 | Summary: My.Qltest; N; false; op_CheckedAdditionAssignment; (My.Qltest.N); ; Argument[0]; Argument[this]; taint; manual |
|
||||
| 36 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; Method1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 37 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; StaticMethod1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 38 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; get_Property1; (System.Object); ; Argument[0].SyntheticField[TestExtensions.Property1]; ReturnValue; value; manual |
|
||||
| 39 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; set_Property1; (System.Object,System.Object); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.Property1]; value; manual |
|
||||
| 40 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 41 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericStaticMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 42 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; get_GenericProperty1; (T); ; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; ReturnValue; value; manual |
|
||||
| 43 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; set_GenericProperty1; (T,T); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; value; manual |
|
||||
| 34 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; Method1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 35 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; StaticMethod1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 36 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; get_Property1; (System.Object); ; Argument[0].SyntheticField[TestExtensions.Property1]; ReturnValue; value; manual |
|
||||
| 37 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; set_Property1; (System.Object,System.Object); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.Property1]; value; manual |
|
||||
| 38 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 39 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericStaticMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 40 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; get_GenericProperty1; (T); ; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; ReturnValue; value; manual |
|
||||
| 41 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; set_GenericProperty1; (T,T); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; value; manual |
|
||||
edges
|
||||
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | ExternalFlow.cs:10:29:10:32 | access to local variable arg1 : Object | provenance | |
|
||||
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | provenance | |
|
||||
@@ -164,77 +162,69 @@ edges
|
||||
| ExternalFlow.cs:373:17:373:19 | access to local variable obj : Object | ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:373:23:373:34 | object creation of type Object : Object | ExternalFlow.cs:373:17:373:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:374:17:374:18 | access to local variable o1 : Object | ExternalFlow.cs:375:18:375:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:374:22:374:24 | access to local variable obj : Object | ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:374:22:374:24 | access to local variable obj : Object | ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | provenance | MaD:34 |
|
||||
| ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | ExternalFlow.cs:374:17:374:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:377:17:377:18 | access to local variable o2 : Object | ExternalFlow.cs:378:18:378:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | ExternalFlow.cs:377:17:377:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | provenance | MaD:34 |
|
||||
| ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:383:23:383:34 | object creation of type Object : Object | ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:384:17:384:18 | access to local variable o1 : Object | ExternalFlow.cs:385:18:385:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | ExternalFlow.cs:384:17:384:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | provenance | MaD:35 |
|
||||
| ExternalFlow.cs:387:17:387:18 | access to local variable o2 : Object | ExternalFlow.cs:388:18:388:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | ExternalFlow.cs:387:17:387:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | provenance | MaD:35 |
|
||||
| ExternalFlow.cs:393:17:393:19 | access to local variable obj : Object | ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:393:23:393:34 | object creation of type Object : Object | ExternalFlow.cs:393:17:393:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | |
|
||||
| ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:395:17:395:18 | access to local variable o1 : Object | ExternalFlow.cs:396:18:396:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | ExternalFlow.cs:395:17:395:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:401:17:401:19 | access to local variable obj : Object | ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:401:23:401:34 | object creation of type Object : Object | ExternalFlow.cs:401:17:401:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | |
|
||||
| ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:403:17:403:18 | access to local variable o1 : Object | ExternalFlow.cs:404:18:404:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | ExternalFlow.cs:403:17:403:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:409:23:409:34 | object creation of type Object : Object | ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:410:17:410:18 | access to local variable o1 : Object | ExternalFlow.cs:411:18:411:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | ExternalFlow.cs:410:17:410:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:413:17:413:18 | access to local variable o2 : Object | ExternalFlow.cs:414:18:414:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | ExternalFlow.cs:413:17:413:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:420:17:420:18 | access to local variable o1 : Object | ExternalFlow.cs:421:18:421:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | ExternalFlow.cs:420:17:420:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:423:17:423:18 | access to local variable o2 : Object | ExternalFlow.cs:424:18:424:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | ExternalFlow.cs:423:17:423:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:429:17:429:19 | access to local variable obj : Object | ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | ExternalFlow.cs:429:17:429:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [property GenericProperty1] : Object | ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [property GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [property GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:43 |
|
||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:431:17:431:18 | access to local variable o1 : Object | ExternalFlow.cs:432:18:432:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [property GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | |
|
||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | MaD:42 |
|
||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | ExternalFlow.cs:431:17:431:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:437:17:437:19 | access to local variable obj : Object | ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | ExternalFlow.cs:437:17:437:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:43 |
|
||||
| ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:439:17:439:18 | access to local variable o1 : Object | ExternalFlow.cs:440:18:440:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | ExternalFlow.cs:439:17:439:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | provenance | MaD:42 |
|
||||
| ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:455:22:455:28 | object creation of type N : N | ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | ExternalFlow.cs:457:18:457:18 | access to parameter n | provenance | |
|
||||
| ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | provenance | MaD:34 |
|
||||
| ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:462:22:462:28 | object creation of type N : N | ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | ExternalFlow.cs:467:18:467:18 | access to parameter n | provenance | |
|
||||
| ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | provenance | MaD:35 |
|
||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | provenance | MaD:40 |
|
||||
nodes
|
||||
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | semmle.label | access to local variable arg1 : Object |
|
||||
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
|
||||
@@ -453,16 +443,6 @@ nodes
|
||||
| ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | semmle.label | call to extension accessor get_GenericProperty1 : Object |
|
||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | semmle.label | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object |
|
||||
| ExternalFlow.cs:440:18:440:19 | access to local variable o1 | semmle.label | access to local variable o1 |
|
||||
| ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:455:22:455:28 | object creation of type N : N | semmle.label | object creation of type N : N |
|
||||
| ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | semmle.label | [post] access to parameter n : N |
|
||||
| ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:457:18:457:18 | access to parameter n | semmle.label | access to parameter n |
|
||||
| ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:462:22:462:28 | object creation of type N : N | semmle.label | object creation of type N : N |
|
||||
| ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | semmle.label | [post] access to parameter n : N |
|
||||
| ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:467:18:467:18 | access to parameter n | semmle.label | access to parameter n |
|
||||
subpaths
|
||||
| ExternalFlow.cs:84:29:84:32 | access to local variable objs : null [element] : Object | ExternalFlow.cs:84:35:84:35 | o : Object | ExternalFlow.cs:84:40:84:40 | access to parameter o : Object | ExternalFlow.cs:84:25:84:41 | call to method Map<Object,Object> : T[] [element] : Object |
|
||||
invalidModelRow
|
||||
@@ -509,5 +489,3 @@ invalidModelRow
|
||||
| ExternalFlow.cs:424:18:424:19 | access to local variable o2 | ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | ExternalFlow.cs:424:18:424:19 | access to local variable o2 | $@ | ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:432:18:432:19 | access to local variable o1 | ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | ExternalFlow.cs:432:18:432:19 | access to local variable o1 | $@ | ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:440:18:440:19 | access to local variable o1 | ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | ExternalFlow.cs:440:18:440:19 | access to local variable o1 | $@ | ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:457:18:457:18 | access to parameter n | ExternalFlow.cs:455:22:455:28 | object creation of type N : N | ExternalFlow.cs:457:18:457:18 | access to parameter n | $@ | ExternalFlow.cs:455:22:455:28 | object creation of type N : N | object creation of type N : N |
|
||||
| ExternalFlow.cs:467:18:467:18 | access to parameter n | ExternalFlow.cs:462:22:462:28 | object creation of type N : N | ExternalFlow.cs:467:18:467:18 | access to parameter n | $@ | ExternalFlow.cs:462:22:462:28 | object creation of type N : N | object creation of type N : N |
|
||||
|
||||
@@ -53,8 +53,6 @@ extensions:
|
||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "GenericStaticMethod1", "(T)", "", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "get_GenericProperty1", "(T)", "", "Argument[0].SyntheticField[TestExtensions.GenericProperty1]", "ReturnValue", "value", "manual"]
|
||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "set_GenericProperty1", "(T,T)", "", "Argument[1]", "Argument[0].SyntheticField[TestExtensions.GenericProperty1]", "value", "manual"]
|
||||
- ["My.Qltest", "N", false, "op_AdditionAssignment", "(My.Qltest.N)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["My.Qltest", "N", false, "op_CheckedAdditionAssignment", "(My.Qltest.N)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/csharp-all
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
string foo() {
|
||||
result = concat(string x | x = [0 .. 10].toString() | x order by x desc, ", ") // $ Alert // BAD
|
||||
result = concat(string x | x = [0 .. 10].toString() | x order by x desc, ", ") // BAD
|
||||
or
|
||||
result = concat(string x | x = [0 .. 10].toString() | x, ", " order by x desc) // GOOD
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/bugs/OrderByConst.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/bugs/OrderByConst.ql
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/bugs/SumWithoutDomain.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/bugs/SumWithoutDomain.ql
|
||||
@@ -1,6 +1,6 @@
|
||||
// Result is 3 and not 4
|
||||
int foo() {
|
||||
result = sum([1, 1, 2]) // $ Alert // <- Alert here
|
||||
result = sum([1, 1, 2]) // <- Alert here
|
||||
}
|
||||
|
||||
// Ok - false negative
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/overlay/InlineOverlayCaller.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/overlay/InlineOverlayCaller.ql
|
||||
|
||||
@@ -4,7 +4,7 @@ module;
|
||||
import ql
|
||||
|
||||
pragma[inline]
|
||||
predicate foo(int x) { x = 42 } // $ Alert
|
||||
predicate foo(int x) { x = 42 }
|
||||
|
||||
overlay[caller]
|
||||
pragma[inline]
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/performance/AbstractClassImport.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/performance/AbstractClassImport.ql
|
||||
@@ -1,4 +1,4 @@
|
||||
import ql
|
||||
import AbstractClassImportTest2
|
||||
|
||||
abstract class Base extends AstNode { } // $ Alert
|
||||
abstract class Base extends AstNode { }
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/performance/MissingNoinline.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/performance/MissingNoinline.ql
|
||||
@@ -5,7 +5,7 @@ import ql
|
||||
*
|
||||
* This predicate exists to fix a join order.
|
||||
*/
|
||||
predicate missingNoInline(AddExpr add, Expr e1, Expr e2) { // $ Alert
|
||||
predicate missingNoInline(AddExpr add, Expr e1, Expr e2) {
|
||||
// BAD
|
||||
add.getLeftOperand() = e1 and
|
||||
add.getRightOperand() = e2
|
||||
|
||||
@@ -13,21 +13,21 @@ class MyStr extends string {
|
||||
predicate bad1(Big b) {
|
||||
b.toString().matches("%foo")
|
||||
or
|
||||
any() // $ Alert
|
||||
any()
|
||||
}
|
||||
|
||||
int bad2() {
|
||||
exists(Big big, Small small |
|
||||
result = big.toString().toInt()
|
||||
or
|
||||
result = small.toString().toInt() // $ Alert
|
||||
result = small.toString().toInt()
|
||||
)
|
||||
}
|
||||
|
||||
float bad3(Big t) {
|
||||
result = [1 .. 10].toString().toFloat() or
|
||||
result = [11 .. 20].toString().toFloat() or
|
||||
result = t.toString().toFloat() or // $ Alert
|
||||
result = t.toString().toFloat() or
|
||||
result = [21 .. 30].toString().toFloat()
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ predicate bad4(Big fromType, Big toType) {
|
||||
or
|
||||
fromType.toString().matches("%foo")
|
||||
or
|
||||
helper(toType, fromType) // $ Alert
|
||||
helper(toType, fromType)
|
||||
}
|
||||
|
||||
predicate good2(Big t) {
|
||||
@@ -71,7 +71,7 @@ predicate mixed1(Big good, Small small) {
|
||||
small.toString().matches("%foo") and
|
||||
// the use of good is fine, the comparison further up binds it.
|
||||
// the same is not true for bad.
|
||||
(bad.toString().matches("%foo") or good.toString().regexpMatch("foo.*")) and // $ Alert
|
||||
(bad.toString().matches("%foo") or good.toString().regexpMatch("foo.*")) and
|
||||
small.toString().regexpMatch(".*foo")
|
||||
)
|
||||
}
|
||||
@@ -112,7 +112,7 @@ predicate good5(Big bb, Big v, boolean certain) {
|
||||
)
|
||||
}
|
||||
|
||||
predicate bad5(Big bb) { if none() then bb.toString().matches("%foo") else any() } // $ Alert
|
||||
predicate bad5(Big bb) { if none() then bb.toString().matches("%foo") else any() }
|
||||
|
||||
pragma[inline]
|
||||
predicate good5(Big a, Big b) {
|
||||
@@ -126,12 +126,12 @@ predicate bad6(Big a) {
|
||||
(
|
||||
a.toString().matches("%foo") // bad
|
||||
or
|
||||
any() // $ Alert
|
||||
any()
|
||||
) and
|
||||
(
|
||||
a.toString().matches("%foo") // also bad
|
||||
or
|
||||
any() // $ Alert
|
||||
any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ class HasField extends Big {
|
||||
HasField() {
|
||||
field = this
|
||||
or
|
||||
this.toString().matches("%foo") // $ Alert // <- field only defined here.
|
||||
this.toString().matches("%foo") // <- field only defined here.
|
||||
}
|
||||
|
||||
Big getField() { result = field }
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/performance/VarUnusedInDisjunct.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/performance/VarUnusedInDisjunct.ql
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/AcronymsShouldBeCamelCase.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/AcronymsShouldBeCamelCase.ql
|
||||
@@ -1,13 +1,13 @@
|
||||
// BAD
|
||||
predicate isXML() { any() } // $ Alert
|
||||
predicate isXML() { any() }
|
||||
|
||||
// GOOD [ AES is exceptional ]
|
||||
predicate isAES() { any() }
|
||||
|
||||
// BAD
|
||||
newtype TXMLElements = // $ Alert
|
||||
newtype TXMLElements =
|
||||
TXmlElement() or // GOOD
|
||||
TXMLElement() // $ Alert // BAD
|
||||
TXMLElement() // BAD
|
||||
|
||||
// GOOD
|
||||
newtype TIRFunction = MkIRFunction()
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/CouldBeCast.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/CouldBeCast.ql
|
||||
@@ -1,20 +1,20 @@
|
||||
bindingset[i]
|
||||
predicate foo(int i) {
|
||||
exists(Even j | j = i) // $ Alert // NOT OK
|
||||
exists(Even j | j = i) // NOT OK
|
||||
or
|
||||
exists(Even j | j = i | j % 4 = 0) // OK
|
||||
or
|
||||
any(Even j | j = i) = 2 // $ Alert // NOT OK
|
||||
any(Even j | j = i) = 2 // NOT OK
|
||||
or
|
||||
any(Even j | j = i | j) = 2 // $ Alert // NOT OK
|
||||
any(Even j | j = i | j) = 2 // NOT OK
|
||||
or
|
||||
any(Even j | j = i | j * 2) = 4 // OK
|
||||
or
|
||||
any(Even j | j = i and j % 4 = 0 | j) = 4 // OK
|
||||
or
|
||||
any(int j | j = i) = 2 // $ Alert // NOT OK
|
||||
any(int j | j = i) = 2 // NOT OK
|
||||
or
|
||||
exists(int j | j = i) // $ Alert // NOT OK
|
||||
exists(int j | j = i) // NOT OK
|
||||
}
|
||||
|
||||
class Even extends int {
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/DataFlowConfigModuleNaming.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/DataFlowConfigModuleNaming.ql
|
||||
@@ -8,14 +8,14 @@ module EmptyConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
// BAD - does not end with "Config"
|
||||
module EmptyConfiguration implements DataFlow::ConfigSig { // $ Alert
|
||||
module EmptyConfiguration implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node src) { none() }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { none() }
|
||||
}
|
||||
|
||||
// BAD - does not end with "Config"
|
||||
module EmptyFlow implements DataFlow::ConfigSig { // $ Alert
|
||||
module EmptyFlow implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node src) { none() }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { none() }
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/DeadCode.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/DeadCode.ql
|
||||
@@ -1,11 +1,11 @@
|
||||
import ql
|
||||
|
||||
private module Mixed {
|
||||
private predicate dead1() { none() } // $ Alert
|
||||
private predicate dead1() { none() }
|
||||
|
||||
predicate alive1() { none() }
|
||||
|
||||
predicate dead2() { none() } // $ Alert
|
||||
predicate dead2() { none() }
|
||||
}
|
||||
|
||||
predicate usesAlive() { Mixed::alive1() }
|
||||
@@ -43,7 +43,7 @@ private module Input1 implements InputSig {
|
||||
predicate foo() { any() }
|
||||
}
|
||||
|
||||
private module Input2 implements InputSig { // $ Alert
|
||||
private module Input2 implements InputSig {
|
||||
predicate foo() { any() }
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ private module Input3 implements InputSig {
|
||||
|
||||
module M1 = ParameterizedModule<Input1>;
|
||||
|
||||
private module M2 = ParameterizedModule<Input2>; // $ Alert
|
||||
private module M2 = ParameterizedModule<Input2>;
|
||||
|
||||
import ParameterizedModule<Input3>
|
||||
|
||||
@@ -65,7 +65,7 @@ private class CImpl1 extends AstNode { }
|
||||
|
||||
final class CPublic1 = CImpl1;
|
||||
|
||||
private class CImpl2 extends AstNode { } // $ Alert
|
||||
private class CImpl2 extends AstNode { }
|
||||
|
||||
overlay[discard_entity]
|
||||
private predicate discard(@foo x) { any() }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class C1 extends int {
|
||||
int field; // $ Alert // BAD
|
||||
int field; // BAD
|
||||
|
||||
C1() {
|
||||
this = field and
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/FieldOnlyUsedInCharPred.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/FieldOnlyUsedInCharPred.ql
|
||||
|
||||
@@ -7,5 +7,5 @@ class Foo extends string {
|
||||
|
||||
string getBarWithThis() { result = this.getBar() }
|
||||
|
||||
string getBarWithoutThis() { result = getBar() } // $ Alert
|
||||
string getBarWithoutThis() { result = getBar() }
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@ class Foo extends string {
|
||||
|
||||
string getBar() { result = "bar" }
|
||||
|
||||
string getBarWithoutThis() { result = getBar() } // $ Alert
|
||||
string getBarWithoutThis() { result = getBar() }
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/ImplicitThis.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/ImplicitThis.ql
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
predicate test1(int param1, int param2, int param3) { none() } // OK
|
||||
|
||||
/** `param1`, `par2` */
|
||||
predicate test2(int param1, int param2) { none() } // $ Alert // NOT OK - `par2` is not a parameter, and `param2` has no documentation
|
||||
predicate test2(int param1, int param2) { none() } // NOT OK - `par2` is not a parameter, and `param2` has no documentation
|
||||
|
||||
/** `param1`, `par2 + par3` */
|
||||
predicate test3(int param1, int par2, int par3) { none() } // OK
|
||||
@@ -11,4 +11,4 @@ predicate test3(int param1, int par2, int par3) { none() } // OK
|
||||
predicate test4(int param1, int param2) { none() } // OK - the QLDoc mentions none of the parameters, that's OK
|
||||
|
||||
/** the param1 parameter is mentioned in a non-code block, but the `par2` parameter is misspelled */
|
||||
predicate test5(int param1, int param2) { none() } // $ Alert // NOT OK - the `param1` parameter is "documented" in clear text, but `par2` is misspelled
|
||||
predicate test5(int param1, int param2) { none() } // NOT OK - the `param1` parameter is "documented" in clear text, but `par2` is misspelled
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/MissingParameterInQlDoc.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/MissingParameterInQlDoc.ql
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/MissingQualityMetadata.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/MissingQualityMetadata.ql
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* @tags quality
|
||||
* maintainability
|
||||
* error-handling
|
||||
*/ // $ Alert
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* @tags quality
|
||||
* maintainability
|
||||
* reliability
|
||||
*/ // $ Alert
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @id ql/quality-query-test
|
||||
* @tags quality
|
||||
* someothertag
|
||||
*/ // $ Alert
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* @tags quality
|
||||
* reliability
|
||||
* readability
|
||||
*/ // $ Alert
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/MissingSecurityMetadata.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/MissingSecurityMetadata.ql
|
||||
@@ -7,7 +7,7 @@
|
||||
* @precision very-high
|
||||
* @id ql/some-query
|
||||
* @tags quality
|
||||
*/ // $ Alert
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @id ql/some-query
|
||||
* @tags quality
|
||||
* security
|
||||
*/ // $ Alert
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/Misspelling.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/Misspelling.ql
|
||||
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* A string that's deliberately mispelled (and so is that last word).
|
||||
*/ // $ Alert
|
||||
class PublicallyAccessible extends string { // $ Alert
|
||||
int numOccurences; // $ Alert // should be 'occurrences'
|
||||
*/
|
||||
class PublicallyAccessible extends string {
|
||||
int numOccurences; // should be 'occurrences'
|
||||
|
||||
PublicallyAccessible() { this = "publically" and numOccurences = 123 }
|
||||
|
||||
// should be argument
|
||||
predicate hasAgrument() { none() } // $ Alert
|
||||
predicate hasAgrument() { none() }
|
||||
|
||||
int getNum() { result = numOccurences }
|
||||
}
|
||||
@@ -15,8 +15,8 @@ class PublicallyAccessible extends string { // $ Alert
|
||||
/**
|
||||
* A class whose name contains a British-English spelling.
|
||||
* And here's the word 'colour'.
|
||||
*/ // $ Alert
|
||||
class AnalysedInt extends int { // $ Alert
|
||||
*/
|
||||
class AnalysedInt extends int {
|
||||
AnalysedInt() { this = 7 }
|
||||
|
||||
// 'analyses' should not be flagged
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
* This should be QLDoc.
|
||||
*/ // $ Alert
|
||||
*/
|
||||
|
||||
/**
|
||||
* this is fine
|
||||
*/
|
||||
predicate foo() { any() }
|
||||
|
||||
/* Note: this is bad. */ // $ Alert
|
||||
/* Note: this is bad. */
|
||||
class Foo extends string {
|
||||
Foo() { this = "FOo" }
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/NonDocBlock.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/NonDocBlock.ql
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/OmittableExists.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/OmittableExists.ql
|
||||
@@ -17,7 +17,7 @@ class Location extends @location_default {
|
||||
}
|
||||
|
||||
predicate test() {
|
||||
exists(int i | aPredicate(i)) // $ Alert // BAD
|
||||
exists(int i | aPredicate(i)) // BAD
|
||||
or
|
||||
exists(int i | aPredicate(i) or anotherPredicate(i)) // BAD [NOT DETECTED]
|
||||
or
|
||||
|
||||
@@ -1 +1 @@
|
||||
| Test3.qlref:1:1:1:23 | query: ... uery.ql | Query test does not use inline test expectations. |
|
||||
| Test3.qlref:1:1:1:22 | query: ... uery.ql | Query test does not use inline test expectations. |
|
||||
|
||||
@@ -1 +1 @@
|
||||
query: ProblemQuery.ql
|
||||
query: ProblemQuery.ql
|
||||
@@ -2,10 +2,10 @@ class Foo extends string {
|
||||
Foo() { this = "Foo" }
|
||||
}
|
||||
|
||||
predicate test(Foo f) { f.(Foo).toString() = "X" } // $ Alert
|
||||
predicate test(Foo f) { f.(Foo).toString() = "X" }
|
||||
|
||||
predicate test2(Foo a, Foo b) { a.(Foo) = b } // $ Alert
|
||||
predicate test2(Foo a, Foo b) { a.(Foo) = b }
|
||||
|
||||
predicate called(Foo a) { a.toString() = "X" }
|
||||
|
||||
predicate test3(string s) { called(s.(Foo)) } // $ Alert
|
||||
predicate test3(string s) { called(s.(Foo)) }
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/RedundantCast.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/RedundantCast.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
import folder.A // $ Alert
|
||||
import folder.A
|
||||
import folder.B
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/RedundantImport.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/RedundantImport.ql
|
||||
@@ -6,7 +6,7 @@ module Test1 {
|
||||
}
|
||||
|
||||
class Bar extends Foo {
|
||||
override Foo pred() { result = Foo.super.pred() } // $ Alert // BAD
|
||||
override Foo pred() { result = Foo.super.pred() } // BAD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ module Test2 {
|
||||
}
|
||||
|
||||
class Bar extends Foo {
|
||||
override Foo pred() { result = super.pred() } // $ Alert // BAD
|
||||
override Foo pred() { result = super.pred() } // BAD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ module Test8 {
|
||||
}
|
||||
|
||||
class Bar extends Foo {
|
||||
override predicate pred(Foo f) { super.pred(f) } // $ Alert // BAD
|
||||
override predicate pred(Foo f) { super.pred(f) } // BAD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,15 +121,15 @@ module Test9 {
|
||||
class Bar extends Foo {
|
||||
Bar() { this = 1 }
|
||||
|
||||
override Foo pred() { Foo.super.pred() = result } // $ Alert // BAD
|
||||
override Foo pred() { Foo.super.pred() = result } // BAD
|
||||
}
|
||||
|
||||
class Baz1 extends Foo, Bar {
|
||||
override Foo pred() { Foo.super.pred() = result } // $ Alert // BAD
|
||||
override Foo pred() { Foo.super.pred() = result } // BAD
|
||||
}
|
||||
|
||||
class Baz2 extends Foo, Baz1 {
|
||||
override Foo pred() { Baz1.super.pred() = result } // $ Alert // BAD
|
||||
override Foo pred() { Baz1.super.pred() = result } // BAD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ module Test10 {
|
||||
}
|
||||
|
||||
class Baz1 extends Foo, Bar {
|
||||
override Foo pred() { result = Foo.super.pred() } // $ Alert // BAD
|
||||
override Foo pred() { result = Foo.super.pred() } // BAD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,19 +161,19 @@ module Test11 {
|
||||
class Bar1 extends Foo {
|
||||
Bar1() { this = [1 .. 3] }
|
||||
|
||||
override Foo pred() { Foo.super.pred() = result } // $ Alert // BAD
|
||||
override Foo pred() { Foo.super.pred() = result } // BAD
|
||||
}
|
||||
|
||||
class Bar2 extends Foo, Bar1 {
|
||||
override Foo pred() { Foo.super.pred() = result } // $ Alert // BAD
|
||||
override Foo pred() { Foo.super.pred() = result } // BAD
|
||||
}
|
||||
|
||||
class Bar3 extends Foo, Bar2 {
|
||||
override Foo pred() { Bar2.super.pred() = result } // $ Alert // BAD
|
||||
override Foo pred() { Bar2.super.pred() = result } // BAD
|
||||
}
|
||||
|
||||
class Bar4 extends Bar2, Bar3 {
|
||||
override Foo pred() { result = Bar2.super.pred() } // $ Alert // BAD
|
||||
override Foo pred() { result = Bar2.super.pred() } // BAD
|
||||
}
|
||||
|
||||
class Bar5 extends Foo {
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/RedundantOverride.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/RedundantOverride.ql
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/SwappedParameterNames.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/SwappedParameterNames.ql
|
||||
@@ -9,5 +9,5 @@ class Correct extends Sup {
|
||||
}
|
||||
|
||||
class Wrong extends Sup {
|
||||
override predicate step(Expr succ, Expr pred) { none() } // $ Alert // <- swapped parameter names
|
||||
override predicate step(Expr succ, Expr pred) { none() } // <- swapped parameter names
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ class Range extends string {
|
||||
string getAChild() { result = "test" }
|
||||
}
|
||||
|
||||
class Inst extends string { // $ Alert
|
||||
class Inst extends string {
|
||||
Range range;
|
||||
|
||||
Inst() { this = range }
|
||||
@@ -12,13 +12,13 @@ class Inst extends string { // $ Alert
|
||||
string getAChild() { result = range.getAChild() }
|
||||
}
|
||||
|
||||
class Inst2 extends string { // $ Alert
|
||||
class Inst2 extends string {
|
||||
Inst2() { this instanceof Range }
|
||||
|
||||
string getAChild() { result = this.(Range).getAChild() }
|
||||
}
|
||||
|
||||
class Inst3 extends string { // $ Alert
|
||||
class Inst3 extends string {
|
||||
Range range;
|
||||
|
||||
Inst3() { this = range }
|
||||
@@ -26,6 +26,6 @@ class Inst3 extends string { // $ Alert
|
||||
Range getRange() { result = range }
|
||||
}
|
||||
|
||||
class Inst4 extends string { // $ Alert
|
||||
class Inst4 extends string {
|
||||
Inst4() { this instanceof Range }
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/UseInstanceofExtension.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/UseInstanceofExtension.ql
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/UseSetLiteral.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/UseSetLiteral.ql
|
||||
@@ -4,7 +4,7 @@ predicate test1(int a) {
|
||||
a = 1 or // BAD
|
||||
a = 2 or
|
||||
a = 3 or
|
||||
a = 4 // $ Alert
|
||||
a = 4
|
||||
}
|
||||
|
||||
predicate test2(int a) {
|
||||
@@ -30,7 +30,7 @@ predicate test5() {
|
||||
test1(1) or // BAD
|
||||
test1(2) or
|
||||
test1(3) or
|
||||
test1(4) // $ Alert
|
||||
test1(4)
|
||||
}
|
||||
|
||||
predicate test6() {
|
||||
@@ -44,7 +44,7 @@ int test7() {
|
||||
1 = result or // BAD
|
||||
2 = result or
|
||||
3 = result or
|
||||
4 = result // $ Alert
|
||||
4 = result
|
||||
}
|
||||
|
||||
predicate test8() {
|
||||
@@ -62,19 +62,19 @@ class MyTest8Class extends int {
|
||||
this = 1 or // BAD
|
||||
this = 2 or
|
||||
this = 3 or
|
||||
this = 4 // $ Alert
|
||||
this = 4
|
||||
) and
|
||||
(
|
||||
s = "1" or // BAD
|
||||
s = "2" or
|
||||
s = "3" or
|
||||
s = "4" // $ Alert
|
||||
s = "4"
|
||||
) and
|
||||
exists(float f |
|
||||
f = 1.0 or // BAD
|
||||
f = 1.5 or
|
||||
f = 2.0 or
|
||||
f = 2.5 // $ Alert
|
||||
f = 2.5
|
||||
)
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ predicate test9(MyTest8Class c) {
|
||||
c.is(1) or // BAD
|
||||
c.is(2) or
|
||||
c.is(3) or
|
||||
c.is(4) // $ Alert
|
||||
c.is(4)
|
||||
}
|
||||
|
||||
predicate test10(MyTest8Class c) {
|
||||
@@ -133,5 +133,5 @@ predicate test14(int a) {
|
||||
(a = 2 or a = 3)
|
||||
or
|
||||
a = 4
|
||||
) // $ Alert
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: queries/style/ValidatePredicateGetReturns.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
queries/style/ValidatePredicateGetReturns.ql
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import ql
|
||||
|
||||
// NOT OK -- Predicate starts with "get" but does not return a value
|
||||
predicate getValue() { none() } // $ Alert
|
||||
predicate getValue() { none() }
|
||||
|
||||
// OK -- starts with get and returns a value
|
||||
string getData() { result = "data" }
|
||||
@@ -22,13 +22,13 @@ predicate getvalue() { none() }
|
||||
predicate retrieveValue() { none() }
|
||||
|
||||
// NOT OK -- starts with get and does not return value
|
||||
predicate getImplementation2() { none() } // $ Alert
|
||||
predicate getImplementation2() { none() }
|
||||
|
||||
// NOT OK -- is an alias for a predicate which does not have a return value
|
||||
predicate getAlias2 = getImplementation2/0; // $ Alert
|
||||
predicate getAlias2 = getImplementation2/0;
|
||||
|
||||
// NOT OK -- starts with as and does not return value
|
||||
predicate asValue() { none() } // $ Alert
|
||||
predicate asValue() { none() }
|
||||
|
||||
// OK -- starts with as but followed by a lowercase letter, probably should be ignored
|
||||
predicate assessment() { none() }
|
||||
@@ -45,7 +45,7 @@ HiddenType getInjectableCompositeActionNode() {
|
||||
predicate implementation4() { none() }
|
||||
|
||||
// NOT OK -- is an alias
|
||||
predicate getAlias4 = implementation4/0; // $ Alert
|
||||
predicate getAlias4 = implementation4/0;
|
||||
|
||||
// OK -- is an alias
|
||||
predicate alias5 = implementation4/0;
|
||||
@@ -58,7 +58,7 @@ predicate edge(int x, int y) { none() }
|
||||
int getDistance(int x) = shortestDistances(root/0, edge/2)(_, x, result)
|
||||
|
||||
// NOT OK -- Higher-order predicate that does not return a value even though has 'get' in the name
|
||||
predicate getDistance2(int x, int y) = shortestDistances(root/0, edge/2)(_, x, y) // $ Alert
|
||||
predicate getDistance2(int x, int y) = shortestDistances(root/0, edge/2)(_, x, y)
|
||||
|
||||
// OK
|
||||
predicate unresolvedAlias = unresolved/0;
|
||||
|
||||
4
ruby/ql/lib/change-notes/2026-06-15-case-else-branch.md
Normal file
4
ruby/ql/lib/change-notes/2026-06-15-case-else-branch.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* The `else` branch of a `case` expression is no longer represented as a `StmtSequence` directly. Instead, a new `CaseElseBranch` AST node wraps the body (a `StmtSequence`). `CaseExpr.getElseBranch()` now returns a `CaseElseBranch`, and the body of the else branch can be accessed via `CaseElseBranch.getBody()`.
|
||||
@@ -377,18 +377,18 @@ class CaseExpr extends ControlExpr instanceof CaseExprImpl {
|
||||
|
||||
/**
|
||||
* Gets the `n`th branch of this case expression, either a `WhenClause`, an
|
||||
* `InClause`, or a `StmtSequence`.
|
||||
* `InClause`, or a `CaseElseBranch`.
|
||||
*/
|
||||
final AstNode getBranch(int n) { result = super.getBranch(n) }
|
||||
|
||||
/**
|
||||
* Gets a branch of this case expression, either a `WhenClause`, an
|
||||
* `InClause`, or a `StmtSequence`.
|
||||
* `InClause`, or a `CaseElseBranch`.
|
||||
*/
|
||||
final AstNode getABranch() { result = this.getBranch(_) }
|
||||
|
||||
/** Gets the `else` branch of this case expression, if any. */
|
||||
final StmtSequence getElseBranch() { result = this.getABranch() }
|
||||
final CaseElseBranch getElseBranch() { result = this.getABranch() }
|
||||
|
||||
/**
|
||||
* Gets the number of branches of this case expression.
|
||||
@@ -533,6 +533,30 @@ class InClause extends AstNode instanceof InClauseImpl {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An `else` branch of a `case` expression.
|
||||
* ```rb
|
||||
* case foo
|
||||
* when 1 then puts "one"
|
||||
* else puts "other"
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class CaseElseBranch extends AstNode instanceof CaseElseBranchImpl {
|
||||
final override string getAPrimaryQlClass() { result = "CaseElseBranch" }
|
||||
|
||||
/** Gets the body of this else branch. */
|
||||
final Stmt getBody() { result = super.getBody() }
|
||||
|
||||
final override string toString() { result = "else ..." }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = AstNode.super.getAChild(pred)
|
||||
or
|
||||
pred = "getBody" and result = this.getBody()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A one-line pattern match using the `=>` operator. For example:
|
||||
* ```rb
|
||||
|
||||
@@ -113,6 +113,9 @@ private module Cached {
|
||||
TBraceBlockSynth(Ast::AstNode parent, int i) { mkSynthChild(BraceBlockKind(), parent, i) } or
|
||||
TBraceBlockReal(Ruby::Block g) { not g.getParent() instanceof Ruby::Lambda } or
|
||||
TBreakStmt(Ruby::Break g) or
|
||||
TCaseElseBranchSynth(Ast::AstNode parent, int i) {
|
||||
mkSynthChild(CaseElseBranchKind(), parent, i)
|
||||
} or
|
||||
TCaseEqExpr(Ruby::Binary g) { g instanceof @ruby_binary_equalequalequal } or
|
||||
TCaseExpr(Ruby::Case g) or
|
||||
TCaseMatchReal(Ruby::CaseMatch g) or
|
||||
@@ -400,14 +403,15 @@ private module Cached {
|
||||
class TAstNodeSynth =
|
||||
TAddExprSynth or TAssignExprSynth or TBitwiseAndExprSynth or TBitwiseOrExprSynth or
|
||||
TBitwiseXorExprSynth or TBraceBlockSynth or TBodyStmtSynth or TBooleanLiteralSynth or
|
||||
TCaseMatchSynth or TClassVariableAccessSynth or TConstantReadAccessSynth or
|
||||
TConstantWriteAccessSynth or TDivExprSynth or TElseSynth or TExponentExprSynth or
|
||||
TGlobalVariableAccessSynth or TIfSynth or TInClauseSynth or TInstanceVariableAccessSynth or
|
||||
TIntegerLiteralSynth or TLShiftExprSynth or TLocalVariableAccessSynth or
|
||||
TLogicalAndExprSynth or TLogicalOrExprSynth or TMethodCallSynth or TModuloExprSynth or
|
||||
TMulExprSynth or TNilLiteralSynth or TRShiftExprSynth or TRangeLiteralSynth or TSelfSynth or
|
||||
TSimpleParameterSynth or TSplatExprSynth or THashSplatExprSynth or TStmtSequenceSynth or
|
||||
TSubExprSynth or TPairSynth or TSimpleSymbolLiteralSynth;
|
||||
TCaseElseBranchSynth or TCaseMatchSynth or TClassVariableAccessSynth or
|
||||
TConstantReadAccessSynth or TConstantWriteAccessSynth or TDivExprSynth or TElseSynth or
|
||||
TExponentExprSynth or TGlobalVariableAccessSynth or TIfSynth or TInClauseSynth or
|
||||
TInstanceVariableAccessSynth or TIntegerLiteralSynth or TLShiftExprSynth or
|
||||
TLocalVariableAccessSynth or TLogicalAndExprSynth or TLogicalOrExprSynth or
|
||||
TMethodCallSynth or TModuloExprSynth or TMulExprSynth or TNilLiteralSynth or
|
||||
TRShiftExprSynth or TRangeLiteralSynth or TSelfSynth or TSimpleParameterSynth or
|
||||
TSplatExprSynth or THashSplatExprSynth or TStmtSequenceSynth or TSubExprSynth or
|
||||
TPairSynth or TSimpleSymbolLiteralSynth;
|
||||
|
||||
/**
|
||||
* Gets the underlying TreeSitter entity for a given AST node. This does not
|
||||
@@ -598,6 +602,8 @@ private module Cached {
|
||||
or
|
||||
result = TBraceBlockSynth(parent, i)
|
||||
or
|
||||
result = TCaseElseBranchSynth(parent, i)
|
||||
or
|
||||
result = TCaseMatchSynth(parent, i)
|
||||
or
|
||||
result = TClassVariableAccessSynth(parent, i, _)
|
||||
@@ -718,6 +724,8 @@ TAstNodeReal fromGenerated(Ruby::AstNode n) { n = toGenerated(result) }
|
||||
|
||||
class TCall = TMethodCall or TYieldCall;
|
||||
|
||||
class TCaseElseBranch = TCaseElseBranchSynth;
|
||||
|
||||
class TCaseMatch = TCaseMatchReal or TCaseMatchSynth;
|
||||
|
||||
class TCase = TCaseExpr or TCaseMatch;
|
||||
|
||||
@@ -19,8 +19,11 @@ class CaseWhenClause extends CaseExprImpl, TCaseExpr {
|
||||
final override Expr getValue() { toGenerated(result) = g.getValue() }
|
||||
|
||||
final override AstNode getBranch(int n) {
|
||||
toGenerated(result) = g.getChild(n) or
|
||||
toGenerated(result) = g.getChild(n)
|
||||
// When branches map directly to WhenClause nodes
|
||||
toGenerated(result) = g.getChild(n) and not g.getChild(n) instanceof Ruby::Else
|
||||
or
|
||||
// The else branch is wrapped in a synthesized CaseElseBranch node
|
||||
g.getChild(n) instanceof Ruby::Else and result = getSynthChild(this, n)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +37,8 @@ class CaseMatch extends CaseExprImpl, TCaseMatchReal {
|
||||
final override AstNode getBranch(int n) {
|
||||
toGenerated(result) = g.getClauses(n)
|
||||
or
|
||||
n = count(g.getClauses(_)) and toGenerated(result) = g.getElse()
|
||||
// The else branch is wrapped in a synthesized CaseElseBranch node
|
||||
n = count(g.getClauses(_)) and exists(g.getElse()) and result = getSynthChild(this, n)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,3 +91,9 @@ class InClauseSynth extends InClauseImpl, TInClauseSynth {
|
||||
|
||||
final override predicate hasUnlessCondition() { none() }
|
||||
}
|
||||
|
||||
class CaseElseBranchImpl extends AstNode, TCaseElseBranch {
|
||||
CaseElseBranchImpl() { this = TCaseElseBranchSynth(_, _) }
|
||||
|
||||
final Stmt getBody() { synthChild(this, 0, result) }
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ newtype TSynthKind =
|
||||
BodyStmtKind() or
|
||||
BooleanLiteralKind(boolean value) { value = true or value = false } or
|
||||
BraceBlockKind() or
|
||||
CaseElseBranchKind() or
|
||||
CaseMatchKind() or
|
||||
ClassVariableAccessKind(ClassVariable v) or
|
||||
DefinedExprKind() or
|
||||
@@ -80,6 +81,8 @@ class SynthKind extends TSynthKind {
|
||||
or
|
||||
this = BraceBlockKind() and result = "BraceBlockKind"
|
||||
or
|
||||
this = CaseElseBranchKind() and result = "CaseElseBranchKind"
|
||||
or
|
||||
this = CaseMatchKind() and result = "CaseMatchKind"
|
||||
or
|
||||
this = ClassVariableAccessKind(_) and result = "ClassVariableAccessKind"
|
||||
@@ -1840,7 +1843,7 @@ private module TestPatternDesugar {
|
||||
or
|
||||
child = SynthChild(InClauseKind()) and i = 1
|
||||
or
|
||||
child = SynthChild(ElseKind()) and i = 2
|
||||
child = SynthChild(CaseElseBranchKind()) and i = 2
|
||||
)
|
||||
or
|
||||
parent = TInClauseSynth(case, 1) and
|
||||
@@ -1851,7 +1854,11 @@ private module TestPatternDesugar {
|
||||
child = SynthChild(BooleanLiteralKind(true)) and i = 1
|
||||
)
|
||||
or
|
||||
parent = TElseSynth(case, 2) and
|
||||
parent = TCaseElseBranchSynth(case, 2) and
|
||||
child = SynthChild(ElseKind()) and
|
||||
i = 0
|
||||
or
|
||||
parent = TElseSynth(TCaseElseBranchSynth(case, 2), 0) and
|
||||
child = SynthChild(BooleanLiteralKind(false)) and
|
||||
i = 0
|
||||
)
|
||||
@@ -1994,3 +2001,61 @@ private module CallableBodySynthesis {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private module CaseElseBranchSynthesis {
|
||||
pragma[nomagic]
|
||||
private predicate caseElseBranchSynthesis(AstNode parent, int i, Child child) {
|
||||
// Wrap the else branch of a real `case`/`when` expression
|
||||
exists(Ruby::Case g, Ruby::Else elseNode, int elseIndex |
|
||||
elseNode = g.getChild(elseIndex) and
|
||||
(
|
||||
// Create the CaseElseBranch wrapper node at the else index
|
||||
parent = TCaseExpr(g) and
|
||||
child = SynthChild(CaseElseBranchKind()) and
|
||||
i = elseIndex
|
||||
or
|
||||
// The body of the CaseElseBranch is the Else node
|
||||
parent = TCaseElseBranchSynth(TCaseExpr(g), elseIndex) and
|
||||
child = RealChildRef(TElseReal(elseNode)) and
|
||||
i = 0
|
||||
)
|
||||
)
|
||||
or
|
||||
// Wrap the else branch of a real `case`/`in` expression
|
||||
exists(Ruby::CaseMatch g, Ruby::Else elseNode, int elseIndex |
|
||||
elseNode = g.getElse() and
|
||||
elseIndex = count(g.getClauses(_)) and
|
||||
(
|
||||
// Create the CaseElseBranch wrapper node at the else index
|
||||
parent = TCaseMatchReal(g) and
|
||||
child = SynthChild(CaseElseBranchKind()) and
|
||||
i = elseIndex
|
||||
or
|
||||
// The body of the CaseElseBranch is the Else node
|
||||
parent = TCaseElseBranchSynth(TCaseMatchReal(g), elseIndex) and
|
||||
child = RealChildRef(TElseReal(elseNode)) and
|
||||
i = 0
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private class CaseElseBranchSynthesisImpl extends Synthesis {
|
||||
final override predicate child(AstNode parent, int i, Child child) {
|
||||
caseElseBranchSynthesis(parent, i, child)
|
||||
}
|
||||
|
||||
final override predicate location(AstNode n, Location l) {
|
||||
// Give the CaseElseBranch the location of the underlying Else node
|
||||
exists(Ruby::Case g, int elseIndex |
|
||||
n = TCaseElseBranchSynth(TCaseExpr(g), elseIndex) and
|
||||
l = g.getChild(elseIndex).getLocation()
|
||||
)
|
||||
or
|
||||
exists(Ruby::CaseMatch g, int elseIndex |
|
||||
elseIndex = count(g.getClauses(_)) and
|
||||
n = TCaseElseBranchSynth(TCaseMatchReal(g), elseIndex) and
|
||||
l = g.getElse().getLocation()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,6 +498,16 @@ module Trees {
|
||||
}
|
||||
}
|
||||
|
||||
private class CaseElseBranchTree extends ControlFlowTree instanceof CaseElseBranch {
|
||||
final override predicate propagatesAbnormal(AstNode child) { child = super.getBody() }
|
||||
|
||||
final override predicate first(AstNode first) { first(super.getBody(), first) }
|
||||
|
||||
final override predicate last(AstNode last, Completion c) { last(super.getBody(), last, c) }
|
||||
|
||||
final override predicate succ(AstNode pred, AstNode succ, Completion c) { none() }
|
||||
}
|
||||
|
||||
private class PatternVariableAccessTree extends LocalVariableAccessTree instanceof LocalVariableWriteAccess,
|
||||
CasePattern
|
||||
{
|
||||
|
||||
@@ -815,8 +815,9 @@ control/cases.rb:
|
||||
# 11| getPattern: [LocalVariableAccess] d
|
||||
# 11| getBody: [StmtSequence] then ...
|
||||
# 12| getStmt: [IntegerLiteral] 200
|
||||
# 13| getBranch/getElseBranch: [StmtSequence] else ...
|
||||
# 14| getStmt: [IntegerLiteral] 300
|
||||
# 13| getBranch/getElseBranch: [CaseElseBranch] else ...
|
||||
# 13| getBody: [StmtSequence] else ...
|
||||
# 14| getStmt: [IntegerLiteral] 300
|
||||
# 18| getStmt: [CaseExpr] case ...
|
||||
# 19| getBranch: [WhenClause] when ...
|
||||
# 19| getPattern: [GTExpr] ... > ...
|
||||
@@ -843,8 +844,9 @@ control/cases.rb:
|
||||
# 27| getPattern: [IntegerLiteral] 5
|
||||
# 27| getBody: [StmtSequence] then ...
|
||||
# 27| getStmt: [BooleanLiteral] true
|
||||
# 28| getBranch/getElseBranch: [StmtSequence] else ...
|
||||
# 28| getStmt: [BooleanLiteral] false
|
||||
# 28| getBranch/getElseBranch: [CaseElseBranch] else ...
|
||||
# 28| getBody: [StmtSequence] else ...
|
||||
# 28| getStmt: [BooleanLiteral] false
|
||||
# 31| getStmt: [CaseExpr] case ...
|
||||
# 31| getValue: [MethodCall] call to expr
|
||||
# 31| getReceiver: [SelfVariableAccess] self
|
||||
@@ -862,8 +864,9 @@ control/cases.rb:
|
||||
# 34| getAnOperand/getArgument/getGreaterOperand/getRightOperand: [IntegerLiteral] 0
|
||||
# 34| getBody: [StmtSequence] then ...
|
||||
# 35| getStmt: [BooleanLiteral] true
|
||||
# 36| getBranch/getElseBranch: [StmtSequence] else ...
|
||||
# 36| getStmt: [BooleanLiteral] false
|
||||
# 36| getBranch/getElseBranch: [CaseElseBranch] else ...
|
||||
# 36| getBody: [StmtSequence] else ...
|
||||
# 36| getStmt: [BooleanLiteral] false
|
||||
# 39| getStmt: [CaseExpr] case ...
|
||||
# 39| getValue: [MethodCall] call to expr
|
||||
# 39| getReceiver: [SelfVariableAccess] self
|
||||
|
||||
@@ -389,8 +389,9 @@ control/cases.rb:
|
||||
# 160| getPrefixElement: [IntegerLiteral] 1
|
||||
# 160| getPrefixElement: [IntegerLiteral] 2
|
||||
# 160| getBody: [BooleanLiteral] true
|
||||
# 160| getBranch/getElseBranch: [StmtSequence] else ...
|
||||
# 160| getStmt: [BooleanLiteral] false
|
||||
# 160| getBranch/getElseBranch: [CaseElseBranch] else ...
|
||||
# 160| getBody: [StmtSequence] else ...
|
||||
# 160| getStmt: [BooleanLiteral] false
|
||||
# 162| [MatchPattern] ... => ...
|
||||
# 162| getDesugared: [CaseExpr] case ...
|
||||
# 162| getValue: [MethodCall] call to expr
|
||||
|
||||
@@ -4,7 +4,7 @@ query predicate caseValues(CaseExpr c, Expr value) { value = c.getValue() }
|
||||
|
||||
query predicate caseNoValues(CaseExpr c) { not exists(c.getValue()) }
|
||||
|
||||
query predicate caseElseBranches(CaseExpr c, StmtSequence elseBranch) {
|
||||
query predicate caseElseBranches(CaseExpr c, CaseElseBranch elseBranch) {
|
||||
elseBranch = c.getElseBranch()
|
||||
}
|
||||
|
||||
|
||||
@@ -333,9 +333,6 @@ pub fn extract(
|
||||
.run_from_tree(&tree, source)
|
||||
.unwrap_or_else(|e| panic!("Desugaring failed for {path_str}: {e}"));
|
||||
traverse_yeast(&ast, &mut visitor);
|
||||
// Comments and other `extra` nodes are not represented in the desugared
|
||||
// AST, so recover them directly from the original parse tree.
|
||||
traverse_extras(&tree, &mut visitor);
|
||||
} else {
|
||||
traverse(&tree, &mut visitor);
|
||||
}
|
||||
@@ -368,8 +365,6 @@ struct Visitor<'a> {
|
||||
ast_node_parent_table_name: String,
|
||||
/// Language-specific name of the tokeninfo table
|
||||
tokeninfo_table_name: String,
|
||||
/// Language-specific name of the trivia tokeninfo table
|
||||
trivia_tokeninfo_table_name: String,
|
||||
/// A lookup table from type name to node types
|
||||
schema: &'a NodeTypeMap,
|
||||
/// A stack for gathering information from child nodes. Whenever a node is
|
||||
@@ -400,33 +395,11 @@ impl<'a> Visitor<'a> {
|
||||
ast_node_location_table_name: format!("{language_prefix}_ast_node_location"),
|
||||
ast_node_parent_table_name: format!("{language_prefix}_ast_node_parent"),
|
||||
tokeninfo_table_name: format!("{language_prefix}_tokeninfo"),
|
||||
trivia_tokeninfo_table_name: format!("{language_prefix}_trivia_tokeninfo"),
|
||||
schema,
|
||||
stack: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits a `TriviaToken` for the given `extra` node (e.g. a comment) from
|
||||
/// the original parse tree. Trivia tokens carry a location and their source
|
||||
/// text, but are not attached to a parent in the (possibly desugared) AST.
|
||||
fn emit_trivia_token(&mut self, node: &Node) {
|
||||
let id = self.trap_writer.fresh_id();
|
||||
let loc = location_for(self, self.file_label, node);
|
||||
let loc_label = location_label(self.trap_writer, loc);
|
||||
self.trap_writer.add_tuple(
|
||||
&self.ast_node_location_table_name,
|
||||
vec![trap::Arg::Label(id), trap::Arg::Label(loc_label)],
|
||||
);
|
||||
self.trap_writer.add_tuple(
|
||||
&self.trivia_tokeninfo_table_name,
|
||||
vec![
|
||||
trap::Arg::Label(id),
|
||||
trap::Arg::Int(node.kind_id() as usize),
|
||||
sliced_source_arg(self.source, node),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
fn record_parse_error(&mut self, loc: trap::Label, mesg: &diagnostics::DiagnosticMessage) {
|
||||
self.diagnostics_writer.write(mesg);
|
||||
let id = self.trap_writer.fresh_id();
|
||||
@@ -862,24 +835,6 @@ fn traverse(tree: &Tree, visitor: &mut Visitor) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Walks the original tree-sitter tree and emits a `TriviaToken` for every
|
||||
/// `extra` node (e.g. a comment). Used to preserve comments that would
|
||||
/// otherwise be lost after a desugaring pass rewrites the tree.
|
||||
fn traverse_extras(tree: &Tree, visitor: &mut Visitor) {
|
||||
emit_extras_in(visitor, tree.root_node());
|
||||
}
|
||||
|
||||
fn emit_extras_in(visitor: &mut Visitor, node: Node<'_>) {
|
||||
let mut cursor = node.walk();
|
||||
for child in node.children(&mut cursor) {
|
||||
if child.is_extra() {
|
||||
visitor.emit_trivia_token(&child);
|
||||
} else {
|
||||
emit_extras_in(visitor, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn traverse_yeast(tree: &yeast::Ast, visitor: &mut Visitor) {
|
||||
use yeast::Cursor;
|
||||
let mut cursor = tree.walk();
|
||||
|
||||
@@ -68,12 +68,7 @@ pub fn generate(
|
||||
let node_parent_table_name = format!("{}_ast_node_parent", &prefix);
|
||||
let token_name = format!("{}_token", &prefix);
|
||||
let tokeninfo_name = format!("{}_tokeninfo", &prefix);
|
||||
let trivia_token_name = format!("{}_trivia_token", &prefix);
|
||||
let trivia_tokeninfo_name = format!("{}_trivia_tokeninfo", &prefix);
|
||||
let reserved_word_name = format!("{}_reserved_word", &prefix);
|
||||
// When a desugaring is configured, comments and other `extra` nodes are
|
||||
// preserved from the original parse tree as `TriviaToken`s.
|
||||
let has_trivia_tokens = language.desugar.is_some();
|
||||
let effective_node_types: String = match language
|
||||
.desugar
|
||||
.as_ref()
|
||||
@@ -90,35 +85,28 @@ pub fn generate(
|
||||
let nodes = node_types::read_node_types_str(&prefix, &effective_node_types)?;
|
||||
let (dbscheme_entries, mut ast_node_members, token_kinds) = convert_nodes(&nodes);
|
||||
ast_node_members.insert(&token_name);
|
||||
if has_trivia_tokens {
|
||||
ast_node_members.insert(&trivia_token_name);
|
||||
}
|
||||
writeln!(&mut dbscheme_writer, "/*- {} dbscheme -*/", language.name)?;
|
||||
dbscheme::write(&mut dbscheme_writer, &dbscheme_entries)?;
|
||||
let token_case = create_token_case(&token_name, token_kinds);
|
||||
let mut dbscheme_tail = vec![
|
||||
dbscheme::Entry::Table(create_tokeninfo(&tokeninfo_name, &token_name)),
|
||||
dbscheme::Entry::Case(token_case),
|
||||
];
|
||||
if has_trivia_tokens {
|
||||
dbscheme_tail.push(dbscheme::Entry::Table(create_tokeninfo(
|
||||
&trivia_tokeninfo_name,
|
||||
&trivia_token_name,
|
||||
)));
|
||||
}
|
||||
dbscheme_tail.push(dbscheme::Entry::Union(dbscheme::Union {
|
||||
name: &ast_node_name,
|
||||
members: ast_node_members,
|
||||
}));
|
||||
dbscheme_tail.push(dbscheme::Entry::Table(create_ast_node_location_table(
|
||||
&node_location_table_name,
|
||||
&ast_node_name,
|
||||
)));
|
||||
dbscheme_tail.push(dbscheme::Entry::Table(create_ast_node_parent_table(
|
||||
&node_parent_table_name,
|
||||
&ast_node_name,
|
||||
)));
|
||||
dbscheme::write(&mut dbscheme_writer, &dbscheme_tail)?;
|
||||
dbscheme::write(
|
||||
&mut dbscheme_writer,
|
||||
&[
|
||||
dbscheme::Entry::Table(create_tokeninfo(&tokeninfo_name, &token_name)),
|
||||
dbscheme::Entry::Case(token_case),
|
||||
dbscheme::Entry::Union(dbscheme::Union {
|
||||
name: &ast_node_name,
|
||||
members: ast_node_members,
|
||||
}),
|
||||
dbscheme::Entry::Table(create_ast_node_location_table(
|
||||
&node_location_table_name,
|
||||
&ast_node_name,
|
||||
)),
|
||||
dbscheme::Entry::Table(create_ast_node_parent_table(
|
||||
&node_parent_table_name,
|
||||
&ast_node_name,
|
||||
)),
|
||||
],
|
||||
)?;
|
||||
|
||||
let mut body = vec![
|
||||
ql::TopLevel::Class(ql_gen::create_ast_node_class(
|
||||
@@ -128,12 +116,6 @@ pub fn generate(
|
||||
)),
|
||||
ql::TopLevel::Class(ql_gen::create_token_class(&token_name, &tokeninfo_name)),
|
||||
];
|
||||
if has_trivia_tokens {
|
||||
body.push(ql::TopLevel::Class(ql_gen::create_trivia_token_class(
|
||||
&trivia_token_name,
|
||||
&trivia_tokeninfo_name,
|
||||
)));
|
||||
}
|
||||
// Only emit the ReservedWord class when there are actually unnamed token
|
||||
// types in the schema (i.e., @{prefix}_reserved_word exists in the dbscheme).
|
||||
// When converting from a YEAST YAML schema that has no unnamed tokens, this
|
||||
|
||||
@@ -199,70 +199,6 @@ pub fn create_token_class<'a>(token_type: &'a str, tokeninfo: &'a str) -> ql::Cl
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates the `TriviaToken` class. Trivia tokens (e.g. comments) are
|
||||
/// `extra` nodes preserved from the original parse tree even when the tree has
|
||||
/// been rewritten by a desugaring pass. They are not part of the regular
|
||||
/// `Token` hierarchy because they do not appear in the (possibly desugared)
|
||||
/// output schema.
|
||||
pub fn create_trivia_token_class<'a>(
|
||||
trivia_token_type: &'a str,
|
||||
trivia_tokeninfo: &'a str,
|
||||
) -> ql::Class<'a> {
|
||||
let trivia_tokeninfo_arity = 3; // id, kind, value
|
||||
let get_value = ql::Predicate {
|
||||
qldoc: Some(String::from("Gets the source text of this trivia token.")),
|
||||
name: "getValue",
|
||||
overridden: false,
|
||||
is_private: false,
|
||||
is_final: true,
|
||||
return_type: Some(ql::Type::String),
|
||||
formal_parameters: vec![],
|
||||
body: create_get_field_expr_for_column_storage(
|
||||
"result",
|
||||
trivia_tokeninfo,
|
||||
1,
|
||||
trivia_tokeninfo_arity,
|
||||
),
|
||||
overlay: None,
|
||||
};
|
||||
let to_string = ql::Predicate {
|
||||
qldoc: Some(String::from(
|
||||
"Gets a string representation of this element.",
|
||||
)),
|
||||
name: "toString",
|
||||
overridden: true,
|
||||
is_private: false,
|
||||
is_final: true,
|
||||
return_type: Some(ql::Type::String),
|
||||
formal_parameters: vec![],
|
||||
body: ql::Expression::Equals(
|
||||
Box::new(ql::Expression::Var("result")),
|
||||
Box::new(ql::Expression::Dot(
|
||||
Box::new(ql::Expression::Var("this")),
|
||||
"getValue",
|
||||
vec![],
|
||||
)),
|
||||
),
|
||||
overlay: None,
|
||||
};
|
||||
ql::Class {
|
||||
qldoc: Some(String::from(
|
||||
"A trivia token, such as a comment, preserved from the original parse tree.",
|
||||
)),
|
||||
name: "TriviaToken",
|
||||
is_abstract: false,
|
||||
supertypes: vec![ql::Type::At(trivia_token_type), ql::Type::Normal("AstNode")]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
characteristic_predicate: None,
|
||||
predicates: vec![
|
||||
get_value,
|
||||
to_string,
|
||||
create_get_a_primary_ql_class("TriviaToken", false),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
// Creates the `ReservedWord` class.
|
||||
pub fn create_reserved_word_class(db_name: &str) -> ql::Class<'_> {
|
||||
let class_name = "ReservedWord";
|
||||
|
||||
@@ -61,18 +61,6 @@ module Unified {
|
||||
override string getAPrimaryQlClass() { result = "Token" }
|
||||
}
|
||||
|
||||
/** A trivia token, such as a comment, preserved from the original parse tree. */
|
||||
class TriviaToken extends @unified_trivia_token, AstNode {
|
||||
/** Gets the source text of this trivia token. */
|
||||
final string getValue() { unified_trivia_tokeninfo(this, _, result) }
|
||||
|
||||
/** Gets a string representation of this element. */
|
||||
final override string toString() { result = this.getValue() }
|
||||
|
||||
/** Gets the name of the primary QL class for this element. */
|
||||
override string getAPrimaryQlClass() { result = "TriviaToken" }
|
||||
}
|
||||
|
||||
/** Gets the file containing the given `node`. */
|
||||
private @file getNodeFile(@unified_ast_node node) {
|
||||
exists(@location_default loc | unified_ast_node_location(node, loc) |
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/** Provides classes for working with comments. */
|
||||
|
||||
private import unified
|
||||
|
||||
/**
|
||||
* A comment appearing in the source code.
|
||||
*/
|
||||
class Comment extends TriviaToken {
|
||||
// At the moment, comments are the only type trivia token we extract
|
||||
/**
|
||||
* Gets the text inside this comment, not counting the delimeters.
|
||||
*/
|
||||
string getCommentText() {
|
||||
result = this.getValue().regexpCapture("//(.*)", 1)
|
||||
or
|
||||
result = this.getValue().regexpCapture("(?s)/\\*(.*)\\*/", 1)
|
||||
}
|
||||
}
|
||||
@@ -334,13 +334,7 @@ case @unified_token.kind of
|
||||
;
|
||||
|
||||
|
||||
unified_trivia_tokeninfo(
|
||||
unique int id: @unified_trivia_token,
|
||||
int kind: int ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
@unified_ast_node = @unified_apply_pattern | @unified_binary_expr | @unified_block_stmt | @unified_call_expr | @unified_expr_condition | @unified_expr_stmt | @unified_guard_if_stmt | @unified_if_stmt | @unified_lambda_expr | @unified_let_pattern_condition | @unified_member_access_expr | @unified_name_expr | @unified_parameter | @unified_sequence_condition | @unified_token | @unified_top_level | @unified_trivia_token | @unified_tuple_pattern | @unified_unary_expr | @unified_var_pattern | @unified_variable_declaration_stmt | @unified_variable_declarator
|
||||
@unified_ast_node = @unified_apply_pattern | @unified_binary_expr | @unified_block_stmt | @unified_call_expr | @unified_expr_condition | @unified_expr_stmt | @unified_guard_if_stmt | @unified_if_stmt | @unified_lambda_expr | @unified_let_pattern_condition | @unified_member_access_expr | @unified_name_expr | @unified_parameter | @unified_sequence_condition | @unified_token | @unified_top_level | @unified_tuple_pattern | @unified_unary_expr | @unified_var_pattern | @unified_variable_declaration_stmt | @unified_variable_declarator
|
||||
|
||||
unified_ast_node_location(
|
||||
unique int node: @unified_ast_node ref,
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
/**
|
||||
* Provides classes for working with the AST, as well as files and locations.
|
||||
*/
|
||||
|
||||
import codeql.Locations
|
||||
import codeql.files.FileSystem
|
||||
import codeql.unified.Ast::Unified
|
||||
import codeql.unified.Comments
|
||||
@@ -1,3 +0,0 @@
|
||||
| comments.swift:1:1:1:22 | // Hello this is swift | Hello this is swift |
|
||||
| comments.swift:3:1:6:3 | /*\n * This is a multi-line comment\n * It should be ignored by the parser\n */ | \n * This is a multi-line comment\n * It should be ignored by the parser\n |
|
||||
| comments.swift:9:5:9:36 | // This is a single-line comment | This is a single-line comment |
|
||||
@@ -1,3 +0,0 @@
|
||||
import unified
|
||||
|
||||
query predicate comments(Comment c, string text) { text = c.getCommentText() }
|
||||
@@ -1,11 +0,0 @@
|
||||
// Hello this is swift
|
||||
|
||||
/*
|
||||
* This is a multi-line comment
|
||||
* It should be ignored by the parser
|
||||
*/
|
||||
|
||||
func hello() {
|
||||
// This is a single-line comment
|
||||
print("Hello, world!")
|
||||
}
|
||||
Reference in New Issue
Block a user