Merge pull request #20136 from github/idrissrio/flexible-constructors

Java: Add test for flexible constructor support
This commit is contained in:
Idriss Riouak
2025-09-04 21:35:02 +02:00
committed by GitHub
11 changed files with 470 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
unexpectedDiagnostic
| <compilation flexible-constructors.testproj/trap/java/diagnostics/diagnostic.trap.gz> | -1 | 0 | file://:0:0:0:0 | Unknown location for jdk.internal.RequiresIdentity+Annotation | Unknown location for jdk.internal.RequiresIdentity+Annotation |

View File

@@ -0,0 +1,95 @@
class A {
A(String msg) {
System.out.println("A: " + msg);
}
}
class B extends A {
B(String input) {
var msg = input.trim().toUpperCase();
super(msg);
}
}
class C {
private final int x;
C(int x) {
if (x < 0) throw new IllegalArgumentException();
super();
this.x = x;
}
}
record R(String name, int score) {
public R(String name) {
var score = name.length();
this(name, score);
}
}
class Outer {
private final String prefix = "outer";
class Inner {
private String full;
Inner(String suffix) {
var combined = prefix + "_" + suffix;
super();
this.full = combined;
}
}
}
class D {
private final String value;
private final int length;
D(String input) {
var processed = input.toLowerCase();
value = processed;
this.length = processed.length();
super();
}
}
class E extends A {
private boolean isValid;
private String processed;
E(String data) {
var temp = data != null ? data.trim() : "";
this.processed = temp;
isValid = !temp.isEmpty();
super(temp);
}
}
class F {
private int x;
private final int y;
private int sum;
F(int a, int b) {
x = a;
this.y = b;
this.sum = a + b;
super();
}
}
class G {
private String instance_val;
{
instance_val = "instance";
}
G(String input) {
var tmp = input != null ? input : "default";
var string = tmp + "_initialized";
super();
this.instance_val = string;
}
}

View File

@@ -0,0 +1,2 @@
| FlexibleConstructors.java:31:7:31:11 | <Expr>; | 1 | <obinit> | Instance initializer call at index 1 |
| FlexibleConstructors.java:89:5:89:5 | <Expr>; | 3 | <obinit> | Instance initializer call at index 3 |

View File

@@ -0,0 +1,8 @@
import java
from MethodCall call, Method m
where
call.getMethod() = m and
m.getName() = "<obinit>"
select call.getEnclosingStmt(), call.getEnclosingStmt().getIndex(), call.getMethod().getName(),
"Instance initializer call at index " + call.getEnclosingStmt().getIndex()

View File

@@ -0,0 +1,125 @@
| FlexibleConstructors.java:1:7:1:7 | A | 0 | class A { |
| FlexibleConstructors.java:1:7:1:7 | A | 1 | A(String msg) { |
| FlexibleConstructors.java:1:7:1:7 | A | 2 | super(); |
| FlexibleConstructors.java:1:7:1:7 | A | 3 | System.out.println("A: " + msg); |
| FlexibleConstructors.java:1:7:1:7 | A | 4 | } |
| FlexibleConstructors.java:1:7:1:7 | A | 5 | } |
| FlexibleConstructors.java:7:7:7:7 | B | 0 | class B { |
| FlexibleConstructors.java:7:7:7:7 | B | 1 | B(String input) { |
| FlexibleConstructors.java:7:7:7:7 | B | 2 | var msg = input.trim().toUpperCase(); |
| FlexibleConstructors.java:7:7:7:7 | B | 3 | super(msg); |
| FlexibleConstructors.java:7:7:7:7 | B | 4 | } |
| FlexibleConstructors.java:7:7:7:7 | B | 5 | } |
| FlexibleConstructors.java:14:7:14:7 | C | 0 | class C { |
| FlexibleConstructors.java:14:7:14:7 | C | 1 | private final int x; |
| FlexibleConstructors.java:14:7:14:7 | C | 2 | |
| FlexibleConstructors.java:14:7:14:7 | C | 3 | C(int x) { |
| FlexibleConstructors.java:14:7:14:7 | C | 4 | if (x < 0) |
| FlexibleConstructors.java:14:7:14:7 | C | 5 | throw new IllegalArgumentException(); |
| FlexibleConstructors.java:14:7:14:7 | C | 6 | super(); |
| FlexibleConstructors.java:14:7:14:7 | C | 7 | this.x = x; |
| FlexibleConstructors.java:14:7:14:7 | C | 8 | } |
| FlexibleConstructors.java:14:7:14:7 | C | 9 | } |
| FlexibleConstructors.java:24:8:24:8 | R | 0 | final class R { |
| FlexibleConstructors.java:24:8:24:8 | R | 1 | public final boolean equals(Object p0) { <missing body> } |
| FlexibleConstructors.java:24:8:24:8 | R | 2 | |
| FlexibleConstructors.java:24:8:24:8 | R | 3 | public final int hashCode() { <missing body> } |
| FlexibleConstructors.java:24:8:24:8 | R | 4 | |
| FlexibleConstructors.java:24:8:24:8 | R | 5 | public String name() { <missing body> } |
| FlexibleConstructors.java:24:8:24:8 | R | 6 | |
| FlexibleConstructors.java:24:8:24:8 | R | 7 | public int score() { <missing body> } |
| FlexibleConstructors.java:24:8:24:8 | R | 8 | |
| FlexibleConstructors.java:24:8:24:8 | R | 9 | public final String toString() { <missing body> } |
| FlexibleConstructors.java:24:8:24:8 | R | 10 | |
| FlexibleConstructors.java:24:8:24:8 | R | 11 | R(String name, int score) { |
| FlexibleConstructors.java:24:8:24:8 | R | 12 | super(); |
| FlexibleConstructors.java:24:8:24:8 | R | 13 | this.name = name; |
| FlexibleConstructors.java:24:8:24:8 | R | 14 | this.score = score; |
| FlexibleConstructors.java:24:8:24:8 | R | 15 | } |
| FlexibleConstructors.java:24:8:24:8 | R | 16 | |
| FlexibleConstructors.java:24:8:24:8 | R | 17 | private final String name; |
| FlexibleConstructors.java:24:8:24:8 | R | 18 | |
| FlexibleConstructors.java:24:8:24:8 | R | 19 | private final int score; |
| FlexibleConstructors.java:24:8:24:8 | R | 20 | |
| FlexibleConstructors.java:24:8:24:8 | R | 21 | public R(String name) { |
| FlexibleConstructors.java:24:8:24:8 | R | 22 | var score = name.length(); |
| FlexibleConstructors.java:24:8:24:8 | R | 23 | this(name, score); |
| FlexibleConstructors.java:24:8:24:8 | R | 24 | } |
| FlexibleConstructors.java:24:8:24:8 | R | 25 | } |
| FlexibleConstructors.java:31:7:31:11 | Outer | 0 | class Outer { |
| FlexibleConstructors.java:31:7:31:11 | Outer | 1 | private void <obinit>() { |
| FlexibleConstructors.java:31:7:31:11 | Outer | 2 | prefix = "outer"; |
| FlexibleConstructors.java:31:7:31:11 | Outer | 3 | } |
| FlexibleConstructors.java:31:7:31:11 | Outer | 4 | |
| FlexibleConstructors.java:31:7:31:11 | Outer | 5 | Outer() { |
| FlexibleConstructors.java:31:7:31:11 | Outer | 6 | super(); |
| FlexibleConstructors.java:31:7:31:11 | Outer | 7 | <obinit>(); |
| FlexibleConstructors.java:31:7:31:11 | Outer | 8 | } |
| FlexibleConstructors.java:31:7:31:11 | Outer | 9 | |
| FlexibleConstructors.java:31:7:31:11 | Outer | 10 | private final String prefix; |
| FlexibleConstructors.java:31:7:31:11 | Outer | 11 | |
| FlexibleConstructors.java:31:7:31:11 | Outer | 12 | class Inner { |
| FlexibleConstructors.java:31:7:31:11 | Outer | 13 | private String full; |
| FlexibleConstructors.java:31:7:31:11 | Outer | 14 | |
| FlexibleConstructors.java:31:7:31:11 | Outer | 15 | Inner(String suffix) { |
| FlexibleConstructors.java:31:7:31:11 | Outer | 16 | var combined = prefix + "_" + suffix; |
| FlexibleConstructors.java:31:7:31:11 | Outer | 17 | super(); |
| FlexibleConstructors.java:31:7:31:11 | Outer | 18 | this.full = combined; |
| FlexibleConstructors.java:31:7:31:11 | Outer | 19 | } |
| FlexibleConstructors.java:31:7:31:11 | Outer | 20 | } |
| FlexibleConstructors.java:31:7:31:11 | Outer | 21 | } |
| FlexibleConstructors.java:45:7:45:7 | D | 0 | class D { |
| FlexibleConstructors.java:45:7:45:7 | D | 1 | private final String value; |
| FlexibleConstructors.java:45:7:45:7 | D | 2 | |
| FlexibleConstructors.java:45:7:45:7 | D | 3 | private final int length; |
| FlexibleConstructors.java:45:7:45:7 | D | 4 | |
| FlexibleConstructors.java:45:7:45:7 | D | 5 | D(String input) { |
| FlexibleConstructors.java:45:7:45:7 | D | 6 | var processed = input.toLowerCase(); |
| FlexibleConstructors.java:45:7:45:7 | D | 7 | value = processed; |
| FlexibleConstructors.java:45:7:45:7 | D | 8 | this.length = processed.length(); |
| FlexibleConstructors.java:45:7:45:7 | D | 9 | super(); |
| FlexibleConstructors.java:45:7:45:7 | D | 10 | } |
| FlexibleConstructors.java:45:7:45:7 | D | 11 | } |
| FlexibleConstructors.java:57:7:57:7 | E | 0 | class E { |
| FlexibleConstructors.java:57:7:57:7 | E | 1 | private boolean isValid; |
| FlexibleConstructors.java:57:7:57:7 | E | 2 | |
| FlexibleConstructors.java:57:7:57:7 | E | 3 | private String processed; |
| FlexibleConstructors.java:57:7:57:7 | E | 4 | |
| FlexibleConstructors.java:57:7:57:7 | E | 5 | E(String data) { |
| FlexibleConstructors.java:57:7:57:7 | E | 6 | var temp = data != null ? data.trim() : ""; |
| FlexibleConstructors.java:57:7:57:7 | E | 7 | this.processed = temp; |
| FlexibleConstructors.java:57:7:57:7 | E | 8 | isValid = !temp.isEmpty(); |
| FlexibleConstructors.java:57:7:57:7 | E | 9 | super(temp); |
| FlexibleConstructors.java:57:7:57:7 | E | 10 | } |
| FlexibleConstructors.java:57:7:57:7 | E | 11 | } |
| FlexibleConstructors.java:69:7:69:7 | F | 0 | class F { |
| FlexibleConstructors.java:69:7:69:7 | F | 1 | private int x; |
| FlexibleConstructors.java:69:7:69:7 | F | 2 | |
| FlexibleConstructors.java:69:7:69:7 | F | 3 | private final int y; |
| FlexibleConstructors.java:69:7:69:7 | F | 4 | |
| FlexibleConstructors.java:69:7:69:7 | F | 5 | private int sum; |
| FlexibleConstructors.java:69:7:69:7 | F | 6 | |
| FlexibleConstructors.java:69:7:69:7 | F | 7 | F(int a, int b) { |
| FlexibleConstructors.java:69:7:69:7 | F | 8 | x = a; |
| FlexibleConstructors.java:69:7:69:7 | F | 9 | this.y = b; |
| FlexibleConstructors.java:69:7:69:7 | F | 10 | this.sum = a + b; |
| FlexibleConstructors.java:69:7:69:7 | F | 11 | super(); |
| FlexibleConstructors.java:69:7:69:7 | F | 12 | } |
| FlexibleConstructors.java:69:7:69:7 | F | 13 | } |
| FlexibleConstructors.java:82:7:82:7 | G | 0 | class G { |
| FlexibleConstructors.java:82:7:82:7 | G | 1 | private void <obinit>() { |
| FlexibleConstructors.java:82:7:82:7 | G | 2 | { |
| FlexibleConstructors.java:82:7:82:7 | G | 3 | instance_val = "instance"; |
| FlexibleConstructors.java:82:7:82:7 | G | 4 | } |
| FlexibleConstructors.java:82:7:82:7 | G | 5 | } |
| FlexibleConstructors.java:82:7:82:7 | G | 6 | |
| FlexibleConstructors.java:82:7:82:7 | G | 7 | private String instance_val; |
| FlexibleConstructors.java:82:7:82:7 | G | 8 | |
| FlexibleConstructors.java:82:7:82:7 | G | 9 | G(String input) { |
| FlexibleConstructors.java:82:7:82:7 | G | 10 | var tmp = input != null ? input : "default"; |
| FlexibleConstructors.java:82:7:82:7 | G | 11 | var string = tmp + "_initialized"; |
| FlexibleConstructors.java:82:7:82:7 | G | 12 | super(); |
| FlexibleConstructors.java:82:7:82:7 | G | 13 | <obinit>(); |
| FlexibleConstructors.java:82:7:82:7 | G | 14 | this.instance_val = string; |
| FlexibleConstructors.java:82:7:82:7 | G | 15 | } |
| FlexibleConstructors.java:82:7:82:7 | G | 16 | } |

View File

@@ -0,0 +1,5 @@
import semmle.code.java.PrettyPrintAst
from ClassOrInterface cori, string s, int line
where pp(cori, s, line) and cori.fromSource()
select cori, line, s

View File

@@ -0,0 +1,213 @@
FlexibleConstructors.java:
# 0| [CompilationUnit] FlexibleConstructors
# 1| 1: [Class] A
# 2| 1: [Constructor] A
#-----| 4: (Parameters)
# 2| 0: [Parameter] msg
# 2| 0: [TypeAccess] String
# 2| 5: [BlockStmt] { ... }
# 3| 1: [ExprStmt] <Expr>;
# 3| 0: [MethodCall] println(...)
# 3| -1: [VarAccess] System.out
# 3| -1: [TypeAccess] System
# 3| 0: [AddExpr] ... + ...
# 3| 0: [StringLiteral] "A: "
# 3| 1: [VarAccess] msg
# 7| 2: [Class] B
#-----| -1: (Base Types)
# 7| -1: [TypeAccess] A
# 8| 1: [Constructor] B
#-----| 4: (Parameters)
# 8| 0: [Parameter] input
# 8| 0: [TypeAccess] String
# 8| 5: [BlockStmt] { ... }
# 9| 0: [LocalVariableDeclStmt] var ...;
# 9| 1: [LocalVariableDeclExpr] msg
# 9| 0: [MethodCall] toUpperCase(...)
# 9| -1: [MethodCall] trim(...)
# 9| -1: [VarAccess] input
# 10| 1: [SuperConstructorInvocationStmt] super(...)
# 10| 0: [VarAccess] msg
# 14| 3: [Class] C
# 15| 1: [FieldDeclaration] int x;
# 15| -1: [TypeAccess] int
# 17| 2: [Constructor] C
#-----| 4: (Parameters)
# 17| 0: [Parameter] x
# 17| 0: [TypeAccess] int
# 17| 5: [BlockStmt] { ... }
# 18| 0: [IfStmt] if (...)
# 18| 0: [LTExpr] ... < ...
# 18| 0: [VarAccess] x
# 18| 1: [IntegerLiteral] 0
# 18| 1: [ThrowStmt] throw ...
# 18| 0: [ClassInstanceExpr] new IllegalArgumentException(...)
# 18| -3: [TypeAccess] IllegalArgumentException
# 19| 1: [SuperConstructorInvocationStmt] super(...)
# 20| 2: [ExprStmt] <Expr>;
# 20| 0: [AssignExpr] ...=...
# 20| 0: [VarAccess] this.x
# 20| -1: [ThisAccess] this
# 20| 1: [VarAccess] x
# 24| 4: [Class] R
# 24| 2: [FieldDeclaration] String name;
# 24| 3: [FieldDeclaration] int score;
# 25| 4: [Constructor] R
#-----| 4: (Parameters)
# 25| 0: [Parameter] name
# 25| 0: [TypeAccess] String
# 25| 5: [BlockStmt] { ... }
# 26| 0: [LocalVariableDeclStmt] var ...;
# 26| 1: [LocalVariableDeclExpr] score
# 26| 0: [MethodCall] length(...)
# 26| -1: [VarAccess] name
# 27| 1: [ThisConstructorInvocationStmt] this(...)
# 27| 0: [VarAccess] name
# 27| 1: [VarAccess] score
# 31| 5: [Class] Outer
# 32| 3: [FieldDeclaration] String prefix;
# 32| -1: [TypeAccess] String
# 32| 0: [StringLiteral] "outer"
# 34| 4: [Class] Inner
# 35| 1: [FieldDeclaration] String full;
# 35| -1: [TypeAccess] String
# 37| 2: [Constructor] Inner
#-----| 4: (Parameters)
# 37| 0: [Parameter] suffix
# 37| 0: [TypeAccess] String
# 37| 5: [BlockStmt] { ... }
# 38| 0: [LocalVariableDeclStmt] var ...;
# 38| 1: [LocalVariableDeclExpr] combined
# 38| 0: [AddExpr] ... + ...
# 38| 0: [AddExpr] ... + ...
# 38| 0: [VarAccess] prefix
# 38| 1: [StringLiteral] "_"
# 38| 1: [VarAccess] suffix
# 39| 1: [SuperConstructorInvocationStmt] super(...)
# 40| 2: [ExprStmt] <Expr>;
# 40| 0: [AssignExpr] ...=...
# 40| 0: [VarAccess] this.full
# 40| -1: [ThisAccess] this
# 40| 1: [VarAccess] combined
# 45| 6: [Class] D
# 46| 1: [FieldDeclaration] String value;
# 46| -1: [TypeAccess] String
# 47| 2: [FieldDeclaration] int length;
# 47| -1: [TypeAccess] int
# 49| 3: [Constructor] D
#-----| 4: (Parameters)
# 49| 0: [Parameter] input
# 49| 0: [TypeAccess] String
# 49| 5: [BlockStmt] { ... }
# 50| 0: [LocalVariableDeclStmt] var ...;
# 50| 1: [LocalVariableDeclExpr] processed
# 50| 0: [MethodCall] toLowerCase(...)
# 50| -1: [VarAccess] input
# 51| 1: [ExprStmt] <Expr>;
# 51| 0: [AssignExpr] ...=...
# 51| 0: [VarAccess] value
# 51| 1: [VarAccess] processed
# 52| 2: [ExprStmt] <Expr>;
# 52| 0: [AssignExpr] ...=...
# 52| 0: [VarAccess] this.length
# 52| -1: [ThisAccess] this
# 52| 1: [MethodCall] length(...)
# 52| -1: [VarAccess] processed
# 53| 3: [SuperConstructorInvocationStmt] super(...)
# 57| 7: [Class] E
#-----| -1: (Base Types)
# 57| -1: [TypeAccess] A
# 58| 1: [FieldDeclaration] boolean isValid;
# 58| -1: [TypeAccess] boolean
# 59| 2: [FieldDeclaration] String processed;
# 59| -1: [TypeAccess] String
# 61| 3: [Constructor] E
#-----| 4: (Parameters)
# 61| 0: [Parameter] data
# 61| 0: [TypeAccess] String
# 61| 5: [BlockStmt] { ... }
# 62| 0: [LocalVariableDeclStmt] var ...;
# 62| 1: [LocalVariableDeclExpr] temp
# 62| 0: [ConditionalExpr] ...?...:...
# 62| 0: [NEExpr] ... != ...
# 62| 0: [VarAccess] data
# 62| 1: [NullLiteral] null
# 62| 1: [MethodCall] trim(...)
# 62| -1: [VarAccess] data
# 62| 2: [StringLiteral] ""
# 63| 1: [ExprStmt] <Expr>;
# 63| 0: [AssignExpr] ...=...
# 63| 0: [VarAccess] this.processed
# 63| -1: [ThisAccess] this
# 63| 1: [VarAccess] temp
# 64| 2: [ExprStmt] <Expr>;
# 64| 0: [AssignExpr] ...=...
# 64| 0: [VarAccess] isValid
# 64| 1: [LogNotExpr] !...
# 64| 0: [MethodCall] isEmpty(...)
# 64| -1: [VarAccess] temp
# 65| 3: [SuperConstructorInvocationStmt] super(...)
# 65| 0: [VarAccess] temp
# 69| 8: [Class] F
# 70| 1: [FieldDeclaration] int x;
# 70| -1: [TypeAccess] int
# 71| 2: [FieldDeclaration] int y;
# 71| -1: [TypeAccess] int
# 72| 3: [FieldDeclaration] int sum;
# 72| -1: [TypeAccess] int
# 74| 4: [Constructor] F
#-----| 4: (Parameters)
# 74| 0: [Parameter] a
# 74| 0: [TypeAccess] int
# 74| 1: [Parameter] b
# 74| 0: [TypeAccess] int
# 74| 5: [BlockStmt] { ... }
# 75| 0: [ExprStmt] <Expr>;
# 75| 0: [AssignExpr] ...=...
# 75| 0: [VarAccess] x
# 75| 1: [VarAccess] a
# 76| 1: [ExprStmt] <Expr>;
# 76| 0: [AssignExpr] ...=...
# 76| 0: [VarAccess] this.y
# 76| -1: [ThisAccess] this
# 76| 1: [VarAccess] b
# 77| 2: [ExprStmt] <Expr>;
# 77| 0: [AssignExpr] ...=...
# 77| 0: [VarAccess] this.sum
# 77| -1: [ThisAccess] this
# 77| 1: [AddExpr] ... + ...
# 77| 0: [VarAccess] a
# 77| 1: [VarAccess] b
# 78| 3: [SuperConstructorInvocationStmt] super(...)
# 82| 9: [Class] G
# 83| 2: [FieldDeclaration] String instance_val;
# 83| -1: [TypeAccess] String
# 85| 3: [BlockStmt] { ... }
# 86| 0: [ExprStmt] <Expr>;
# 86| 0: [AssignExpr] ...=...
# 86| 0: [VarAccess] instance_val
# 86| 1: [StringLiteral] "instance"
# 89| 4: [Constructor] G
#-----| 4: (Parameters)
# 89| 0: [Parameter] input
# 89| 0: [TypeAccess] String
# 89| 5: [BlockStmt] { ... }
# 90| 0: [LocalVariableDeclStmt] var ...;
# 90| 1: [LocalVariableDeclExpr] tmp
# 90| 0: [ConditionalExpr] ...?...:...
# 90| 0: [NEExpr] ... != ...
# 90| 0: [VarAccess] input
# 90| 1: [NullLiteral] null
# 90| 1: [VarAccess] input
# 90| 2: [StringLiteral] "default"
# 91| 1: [LocalVariableDeclStmt] var ...;
# 91| 1: [LocalVariableDeclExpr] string
# 91| 0: [AddExpr] ... + ...
# 91| 0: [VarAccess] tmp
# 91| 1: [StringLiteral] "_initialized"
# 92| 2: [SuperConstructorInvocationStmt] super(...)
# 93| 4: [ExprStmt] <Expr>;
# 93| 0: [AssignExpr] ...=...
# 93| 0: [VarAccess] this.instance_val
# 93| -1: [ThisAccess] this
# 93| 1: [VarAccess] string

View File

@@ -0,0 +1 @@
semmle/code/java/PrintAst.ql

View File

@@ -0,0 +1,7 @@
| FlexibleConstructors.java:10:15:10:17 | msg | FlexibleConstructors.java:10:9:10:19 | super(...) | predecessor of explicit super() |
| FlexibleConstructors.java:18:13:18:17 | ... < ... | FlexibleConstructors.java:19:9:19:16 | super(...) | predecessor of explicit super() |
| FlexibleConstructors.java:38:17:38:48 | combined | FlexibleConstructors.java:39:13:39:20 | super(...) | predecessor of explicit super() |
| FlexibleConstructors.java:52:9:52:40 | ...=... | FlexibleConstructors.java:53:9:53:16 | super(...) | predecessor of explicit super() |
| FlexibleConstructors.java:65:15:65:18 | temp | FlexibleConstructors.java:65:9:65:20 | super(...) | predecessor of explicit super() |
| FlexibleConstructors.java:77:9:77:24 | ...=... | FlexibleConstructors.java:78:9:78:16 | super(...) | predecessor of explicit super() |
| FlexibleConstructors.java:91:13:91:41 | string | FlexibleConstructors.java:92:9:92:16 | super(...) | predecessor of explicit super() |

View File

@@ -0,0 +1,11 @@
import java
from ControlFlowNode pred, ControlFlowNode supNode, SuperConstructorInvocationStmt sc
where
supNode.asStmt() = sc and
pred.getASuccessor() = supNode and
pred != supNode and
not pred.asStmt() instanceof BlockStmt and
exists(sc.getEnclosingCallable().getFile().getRelativePath()) and
sc.getLocation().getEndColumn() > sc.getLocation().getStartColumn()
select pred, sc, "predecessor of explicit super()"

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args --release 25 --enable-preview