mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge pull request #6520 from smowton/smowton/feature/allow-local-interfaces
Java: Allow local interfaces
This commit is contained in:
@@ -440,10 +440,10 @@ isAnonymClass(
|
||||
int parent: @classinstancexpr ref
|
||||
);
|
||||
|
||||
#keyset[classid] #keyset[parent]
|
||||
isLocalClass(
|
||||
int classid: @class ref,
|
||||
int parent: @localclassdeclstmt ref
|
||||
#keyset[typeid] #keyset[parent]
|
||||
isLocalClassOrInterface(
|
||||
int typeid: @classorinterface ref,
|
||||
int parent: @localtypedeclstmt ref
|
||||
);
|
||||
|
||||
isDefConstr(
|
||||
@@ -526,7 +526,7 @@ case @stmt.kind of
|
||||
| 15 = @labeledstmt
|
||||
| 16 = @assertstmt
|
||||
| 17 = @localvariabledeclstmt
|
||||
| 18 = @localclassdeclstmt
|
||||
| 18 = @localtypedeclstmt
|
||||
| 19 = @constructorinvocationstmt
|
||||
| 20 = @superconstructorinvocationstmt
|
||||
| 21 = @case
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
<v>223232</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@localclassdeclstmt</k>
|
||||
<k>@localtypedeclstmt</k>
|
||||
<v>349</v>
|
||||
</e>
|
||||
<e>
|
||||
@@ -16910,11 +16910,11 @@
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>isLocalClass</name>
|
||||
<name>isLocalClassOrInterface</name>
|
||||
<cardinality>349</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>classid</k>
|
||||
<k>typeid</k>
|
||||
<v>349</v>
|
||||
</e>
|
||||
<e>
|
||||
@@ -16924,7 +16924,7 @@
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
<dep>
|
||||
<src>classid</src>
|
||||
<src>typeid</src>
|
||||
<trg>parent</trg>
|
||||
<val>
|
||||
<hist>
|
||||
@@ -16941,7 +16941,7 @@
|
||||
</dep>
|
||||
<dep>
|
||||
<src>parent</src>
|
||||
<trg>classid</trg>
|
||||
<trg>typeid</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
|
||||
@@ -456,7 +456,7 @@ private module ControlFlowGraphImpl {
|
||||
or
|
||||
this instanceof EmptyStmt
|
||||
or
|
||||
this instanceof LocalClassDeclStmt
|
||||
this instanceof LocalTypeDeclStmt
|
||||
or
|
||||
this instanceof AssertStmt
|
||||
}
|
||||
|
||||
@@ -40,12 +40,12 @@ class Member extends Element, Annotatable, Modifiable, @member {
|
||||
|
||||
/**
|
||||
* Gets the immediately enclosing callable, if this member is declared in
|
||||
* an anonymous or local class.
|
||||
* an anonymous or local class or interface.
|
||||
*/
|
||||
Callable getEnclosingCallable() {
|
||||
exists(NestedClass nc | this.getDeclaringType() = nc |
|
||||
nc.(AnonymousClass).getClassInstanceExpr().getEnclosingCallable() = result or
|
||||
nc.(LocalClass).getLocalClassDeclStmt().getEnclosingCallable() = result
|
||||
exists(NestedType nt | this.getDeclaringType() = nt |
|
||||
nt.(AnonymousClass).getClassInstanceExpr().getEnclosingCallable() = result or
|
||||
nt.(LocalClassOrInterface).getLocalTypeDeclStmt().getEnclosingCallable() = result
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -877,8 +877,8 @@ private class PpLocalVariableDeclStmt extends PpAst, LocalVariableDeclStmt {
|
||||
}
|
||||
}
|
||||
|
||||
private class PpLocalClassDeclStmt extends PpAst, LocalClassDeclStmt {
|
||||
override PpAst getChild(int i) { i = 0 and result = this.getLocalClass() }
|
||||
private class PpLocalTypeDeclStmt extends PpAst, LocalTypeDeclStmt {
|
||||
override PpAst getChild(int i) { i = 0 and result = this.getLocalType() }
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -303,19 +303,25 @@ final class ClassInstanceExprNode extends ExprStmtNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing a `LocalClassDeclStmt`.
|
||||
* A node representing a `LocalTypeDeclStmt`.
|
||||
*/
|
||||
final class LocalClassDeclStmtNode extends ExprStmtNode {
|
||||
LocalClassDeclStmtNode() { element instanceof LocalClassDeclStmt }
|
||||
final class LocalTypeDeclStmtNode extends ExprStmtNode {
|
||||
LocalTypeDeclStmtNode() { element instanceof LocalTypeDeclStmt }
|
||||
|
||||
override ElementNode getChild(int childIndex) {
|
||||
result = super.getChild(childIndex)
|
||||
or
|
||||
childIndex = 0 and
|
||||
result.getElement() = element.(LocalClassDeclStmt).getLocalClass()
|
||||
result.getElement() = element.(LocalTypeDeclStmt).getLocalType()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Renamed `LocalTypeDeclStmtNode` to reflect the fact that
|
||||
* as of Java 16 interfaces can also be declared locally, not just classes.
|
||||
*/
|
||||
deprecated class LocalClassDeclStmtNode = LocalTypeDeclStmtNode;
|
||||
|
||||
/**
|
||||
* A node representing a `ForStmt`.
|
||||
*/
|
||||
|
||||
@@ -786,20 +786,38 @@ class LocalVariableDeclStmt extends Stmt, @localvariabledeclstmt {
|
||||
override string getAPrimaryQlClass() { result = "LocalVariableDeclStmt" }
|
||||
}
|
||||
|
||||
/** A statement that declares a local class. */
|
||||
class LocalClassDeclStmt extends Stmt, @localclassdeclstmt {
|
||||
/** Gets the local class declared by this statement. */
|
||||
LocalClass getLocalClass() { isLocalClass(result, this) }
|
||||
/** A statement that declares a local class or interface. */
|
||||
class LocalTypeDeclStmt extends Stmt, @localtypedeclstmt {
|
||||
/** Gets the local type declared by this statement. */
|
||||
LocalClassOrInterface getLocalType() { isLocalClassOrInterface(result, this) }
|
||||
|
||||
override string pp() { result = "class " + this.getLocalClass().toString() }
|
||||
/**
|
||||
* DEPRECATED: Renamed `getLocalType` to reflect the fact that
|
||||
* as of Java 16 interfaces can also be declared locally, not just classes.
|
||||
*/
|
||||
deprecated LocalClassOrInterface getLocalClass() { result = this.getLocalType() }
|
||||
|
||||
override string toString() { result = "class ..." }
|
||||
private string getDeclKeyword() {
|
||||
result = "class" and this.getLocalType() instanceof Class
|
||||
or
|
||||
result = "interface" and this.getLocalType() instanceof Interface
|
||||
}
|
||||
|
||||
override string getHalsteadID() { result = "LocalClassDeclStmt" }
|
||||
override string pp() { result = this.getDeclKeyword() + " " + this.getLocalType().toString() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LocalClassDeclStmt" }
|
||||
override string toString() { result = this.getDeclKeyword() + " ..." }
|
||||
|
||||
override string getHalsteadID() { result = "LocalTypeDeclStmt" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LocalTypeDeclStmt" }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Renamed `LocalTypeDeclStmt` to reflect the fact that
|
||||
* as of Java 16 interfaces can also be declared locally, not just classes.
|
||||
*/
|
||||
deprecated class LocalClassDeclStmt = LocalTypeDeclStmt;
|
||||
|
||||
/** An explicit `this(...)` constructor invocation. */
|
||||
class ThisConstructorInvocationStmt extends Stmt, ConstructorCall, @constructorinvocationstmt {
|
||||
/** Gets an argument of this constructor invocation. */
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
* (`Interface`).
|
||||
*
|
||||
* Reference types can be at the top level (`TopLevelType`) or nested (`NestedType`).
|
||||
* Classes can also be local (`LocalClass`) or anonymous (`AnonymousClass`).
|
||||
* Enumerated types (`EnumType`) are a special kind of class.
|
||||
* Classes and interfaces can also be local (`LocalClassOrInterface`, `LocalClass`) or anonymous (`AnonymousClass`).
|
||||
* Enumerated types (`EnumType`) and records (`Record`) are special kinds of classes.
|
||||
*/
|
||||
|
||||
import Member
|
||||
@@ -269,7 +269,7 @@ predicate declaresMember(Type t, @member m) {
|
||||
// Since the type `@member` in the dbscheme includes all `@reftype`s,
|
||||
// anonymous and local classes need to be excluded here.
|
||||
not m instanceof AnonymousClass and
|
||||
not m instanceof LocalClass
|
||||
not m instanceof LocalClassOrInterface
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -608,20 +608,10 @@ class SrcRefType extends RefType {
|
||||
}
|
||||
|
||||
/** A class declaration. */
|
||||
class Class extends RefType, @class {
|
||||
class Class extends ClassOrInterface, @class {
|
||||
/** Holds if this class is an anonymous class. */
|
||||
predicate isAnonymous() { isAnonymClass(this, _) }
|
||||
|
||||
/** Holds if this class is a local class. */
|
||||
predicate isLocal() { isLocalClass(this, _) }
|
||||
|
||||
/** Holds if this class is package protected, that is, neither public nor private nor protected. */
|
||||
predicate isPackageProtected() {
|
||||
not isPrivate() and
|
||||
not isProtected() and
|
||||
not isPublic()
|
||||
}
|
||||
|
||||
override RefType getSourceDeclaration() { classes(this, _, _, result) }
|
||||
|
||||
/**
|
||||
@@ -630,11 +620,13 @@ class Class extends RefType, @class {
|
||||
* Note that a class may inherit annotations from super-classes.
|
||||
*/
|
||||
override Annotation getAnAnnotation() {
|
||||
result = RefType.super.getAnAnnotation()
|
||||
result = ClassOrInterface.super.getAnAnnotation()
|
||||
or
|
||||
exists(AnnotationType tp | tp = result.getType() |
|
||||
tp.isInherited() and
|
||||
not exists(Annotation ann | ann = RefType.super.getAnAnnotation() | ann.getType() = tp) and
|
||||
not exists(Annotation ann | ann = ClassOrInterface.super.getAnAnnotation() |
|
||||
ann.getType() = tp
|
||||
) and
|
||||
result = this.getASupertype().(Class).getAnAnnotation()
|
||||
)
|
||||
}
|
||||
@@ -643,8 +635,6 @@ class Class extends RefType, @class {
|
||||
}
|
||||
|
||||
/**
|
||||
* PREVIEW FEATURE in Java 14. Subject to removal in a future release.
|
||||
*
|
||||
* A record declaration.
|
||||
*/
|
||||
class Record extends Class {
|
||||
@@ -727,12 +717,25 @@ class AnonymousClass extends NestedClass {
|
||||
override string getAPrimaryQlClass() { result = "AnonymousClass" }
|
||||
}
|
||||
|
||||
/** A local class. */
|
||||
class LocalClass extends NestedClass {
|
||||
LocalClass() { this.isLocal() }
|
||||
/** A local class or interface. */
|
||||
class LocalClassOrInterface extends NestedType, ClassOrInterface {
|
||||
LocalClassOrInterface() { this.isLocal() }
|
||||
|
||||
/** Gets the statement that declares this local class. */
|
||||
LocalClassDeclStmt getLocalClassDeclStmt() { isLocalClass(this, result) }
|
||||
LocalTypeDeclStmt getLocalTypeDeclStmt() { isLocalClassOrInterface(this, result) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: renamed `getLocalTypeDeclStmt` to reflect the fact that
|
||||
* as of Java 16 interfaces can also be declared locally.
|
||||
*/
|
||||
deprecated LocalTypeDeclStmt getLocalClassDeclStmt() { result = this.getLocalTypeDeclStmt() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LocalClassOrInterface" }
|
||||
}
|
||||
|
||||
/** A local class. */
|
||||
class LocalClass extends LocalClassOrInterface, NestedClass {
|
||||
LocalClass() { this.isLocal() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LocalClass" }
|
||||
}
|
||||
@@ -842,12 +845,12 @@ class InnerClass extends NestedClass {
|
||||
predicate hasEnclosingInstance() {
|
||||
// JLS 15.9.2. Determining Enclosing Instances
|
||||
not this.(AnonymousClass).getClassInstanceExpr().isInStaticContext() and
|
||||
not this.(LocalClass).getLocalClassDeclStmt().getEnclosingCallable().isStatic()
|
||||
not this.(LocalClass).getLocalTypeDeclStmt().getEnclosingCallable().isStatic()
|
||||
}
|
||||
}
|
||||
|
||||
/** An interface. */
|
||||
class Interface extends RefType, @interface {
|
||||
class Interface extends ClassOrInterface, @interface {
|
||||
override RefType getSourceDeclaration() { interfaces(this, _, _, result) }
|
||||
|
||||
override predicate isAbstract() {
|
||||
@@ -855,21 +858,19 @@ class Interface extends RefType, @interface {
|
||||
any()
|
||||
}
|
||||
|
||||
/** Holds if this interface is package protected, that is, neither public nor private nor protected. */
|
||||
predicate isPackageProtected() {
|
||||
not isPrivate() and
|
||||
not isProtected() and
|
||||
not isPublic()
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Interface" }
|
||||
}
|
||||
|
||||
/** A class or interface. */
|
||||
class ClassOrInterface extends RefType {
|
||||
ClassOrInterface() {
|
||||
this instanceof Class or
|
||||
this instanceof Interface
|
||||
class ClassOrInterface extends RefType, @classorinterface {
|
||||
/** Holds if this class or interface is local. */
|
||||
predicate isLocal() { isLocalClassOrInterface(this, _) }
|
||||
|
||||
/** Holds if this class or interface is package protected, that is, neither public nor private nor protected. */
|
||||
predicate isPackageProtected() {
|
||||
not isPrivate() and
|
||||
not isProtected() and
|
||||
not isPublic()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ private module SsaImpl {
|
||||
/** Gets the definition point of a nested class in the parent scope. */
|
||||
private ControlFlowNode parentDef(NestedClass nc) {
|
||||
nc.(AnonymousClass).getClassInstanceExpr() = result or
|
||||
nc.(LocalClass).getLocalClassDeclStmt() = result
|
||||
nc.(LocalClass).getLocalTypeDeclStmt() = result
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -79,7 +79,7 @@ private module SsaImpl {
|
||||
/** Gets the definition point of a nested class in the parent scope. */
|
||||
private ControlFlowNode parentDef(NestedClass nc) {
|
||||
nc.(AnonymousClass).getClassInstanceExpr() = result or
|
||||
nc.(LocalClass).getLocalClassDeclStmt() = result
|
||||
nc.(LocalClass).getLocalTypeDeclStmt() = result
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -234,10 +234,10 @@ abstract class BusinessInterface extends Interface {
|
||||
abstract SessionEJB getAnEJB();
|
||||
|
||||
/** Holds if this business interface is declared local. */
|
||||
abstract predicate isLocal();
|
||||
abstract predicate isDeclaredLocal();
|
||||
|
||||
/** Holds if this business interface is declared remote. */
|
||||
abstract predicate isRemote();
|
||||
abstract predicate isDeclaredRemote();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -259,14 +259,14 @@ class XmlSpecifiedBusinessInterface extends BusinessInterface {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isLocal() {
|
||||
override predicate isDeclaredLocal() {
|
||||
exists(EjbJarXMLFile f |
|
||||
this.getQualifiedName() =
|
||||
f.getASessionElement().getABusinessLocalElement().getACharactersSet().getCharacters()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isRemote() {
|
||||
override predicate isDeclaredRemote() {
|
||||
exists(EjbJarXMLFile f |
|
||||
this.getQualifiedName() =
|
||||
f.getASessionElement().getABusinessRemoteElement().getACharactersSet().getCharacters()
|
||||
@@ -295,9 +295,9 @@ class AnnotatedBusinessInterface extends BusinessInterface {
|
||||
result.getAnAnnotation().(BusinessInterfaceAnnotation).getANamedType() = this
|
||||
}
|
||||
|
||||
override predicate isLocal() { this instanceof LocalAnnotatedBusinessInterface }
|
||||
override predicate isDeclaredLocal() { this instanceof LocalAnnotatedBusinessInterface }
|
||||
|
||||
override predicate isRemote() { this instanceof RemoteAnnotatedBusinessInterface }
|
||||
override predicate isDeclaredRemote() { this instanceof RemoteAnnotatedBusinessInterface }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -540,7 +540,7 @@ class XmlSpecifiedLocalHomeInterface extends LegacyEjbLocalHomeInterface {
|
||||
class RemoteInterface extends Interface {
|
||||
RemoteInterface() {
|
||||
this instanceof RemoteAnnotatedBusinessInterface or
|
||||
this.(XmlSpecifiedBusinessInterface).isRemote() or
|
||||
this.(XmlSpecifiedBusinessInterface).isDeclaredRemote() or
|
||||
exists(SessionEJB ejb | this = ejb.getARemoteInterface())
|
||||
}
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ where
|
||||
// Remove local classes defined in the dead method - they are reported separately as a dead
|
||||
// class. We keep anonymous class counts, because anonymous classes are not reported
|
||||
// separately.
|
||||
sum(LocalClass localClass |
|
||||
localClass.getLocalClassDeclStmt().getEnclosingCallable() = deadMethod
|
||||
sum(LocalClassOrInterface localClass |
|
||||
localClass.getLocalTypeDeclStmt().getEnclosingCallable() = deadMethod
|
||||
|
|
||||
localClass.getNumberOfLinesOfCode()
|
||||
)
|
||||
|
||||
@@ -122,8 +122,8 @@ where
|
||||
not abortsControlFlow(s) and
|
||||
// Exclude the double semicolon case `if (cond) s;;`.
|
||||
not t instanceof EmptyStmt and
|
||||
// `LocalClassDeclStmt`s yield false positives since their `Location` doesn't include the `class` keyword.
|
||||
not t instanceof LocalClassDeclStmt
|
||||
// `LocalTypeDeclStmt`s yield false positives since their `Location` doesn't include the `class` keyword.
|
||||
not t instanceof LocalTypeDeclStmt
|
||||
select s,
|
||||
"Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation.",
|
||||
t, "the next statement", c, "the control structure"
|
||||
|
||||
@@ -11,7 +11,7 @@ import java
|
||||
abstract private class GeneratedType extends ClassOrInterface {
|
||||
GeneratedType() {
|
||||
not this instanceof AnonymousClass and
|
||||
not this instanceof LocalClass and
|
||||
not this.isLocal() and
|
||||
not this.getPackage() instanceof ExcludedPackage
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user