Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions java/change-notes/2021-04-14-membertype.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
lgtm,codescanning
* A CodeQL class `MemberType` is introduced to describe nested classes. Its `getQualifiedName` method returns `$`-delimited nested type names (for example, `mypackage.Outer$Middle$Inner`), where previously the same type would be named differently depending on whether it was addressed as a `NestedType` or a `Member`.
3 changes: 1 addition & 2 deletions java/ql/src/Performance/InnerClassCouldBeStatic.ql
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ predicate potentiallyStatic(InnerClass c) {
m = a.getEnclosingCallable() and
m.getDeclaringType() = c
) and
not c instanceof AnonymousClass and
not c instanceof LocalClass and
c instanceof MemberType and
forall(
InnerClass other // If nested and non-static, ...
|
Expand Down
4 changes: 1 addition & 3 deletions java/ql/src/semmle/code/java/PrintAst.qll
Original file line number Diff line number Diff line change
Expand Up @@ -433,9 +433,7 @@ final class ClassInterfaceNode extends ElementNode {
or
result.(FieldDeclaration).getAField().getDeclaringType() = ty
or
result.(NestedType).getEnclosingType().getSourceDeclaration() = ty and
not result instanceof AnonymousClass and
not result instanceof LocalClass
result.(MemberType).getEnclosingType().getSourceDeclaration() = ty
or
isInitBlock(ty, result)
}
Expand Down
42 changes: 37 additions & 5 deletions java/ql/src/semmle/code/java/Type.qll
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,12 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
/** Holds if this is a top-level type, which is not nested inside any other types. */
predicate isTopLevel() { this instanceof TopLevelType }

/** Holds if this type is declared in a specified package with the specified name. */
/**
* Holds if this type is declared in a specified package with the specified name.
*
* For nested types the name of the nested type is prefixed with a `$` and appended
* to the name of the enclosing type, which might be a nested type as well.
*/
predicate hasQualifiedName(string package, string type) {
this.getPackage().hasName(package) and type = this.nestedName()
}
Expand All @@ -532,15 +537,26 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
}

/**
* Gets the qualified name of this type.
* Gets the qualified name of this type, consisting of the package name followed by
* a `.` and the name of this type.
*
* For nested types the name of the nested type is prefixed with a `$` and appended
* to the name of the enclosing type, which might be a nested type as well. For example:
* `java.lang.Thread$State`.
*/
string getQualifiedName() {
exists(string pkgName | pkgName = getPackage().getName() |
if pkgName = "" then result = nestedName() else result = pkgName + "." + nestedName()
)
}

/** Gets the nested name of this type. */
/**
* Gets the nested name of this type.
*
* If this type is not a nested type, the result is the same as `getName()`.
* Otherwise the name of the nested type is prefixed with a `$` and appended to
* the name of the enclosing type, which might be a nested type as well.
*/
string nestedName() {
not this instanceof NestedType and result = this.getName()
or
Expand Down Expand Up @@ -788,6 +804,21 @@ class NestedType extends RefType {
}
}

/**
* A nested type which is a direct member of the enclosing type,
* that is, neither an anonymous nor local class.
*/
class MemberType extends NestedType, Member {
/**
* Gets the qualified name of this member type.
*
* The qualified name consists of the package name, a `.`, the name of the declaring
* type (which might be a nested or member type as well), followed by a `$` and the
* name of this member type. For example: `java.lang.Thread$State`.
*/
override string getQualifiedName() { result = NestedType.super.getQualifiedName() }
}

/**
* A class declared within another type.
*
Expand All @@ -797,8 +828,9 @@ class NestedType extends RefType {
class NestedClass extends NestedType, Class { }

/**
* An inner class is a nested class that is neither
* explicitly nor implicitly declared static.
* An inner class is a nested class that is neither explicitly nor
* implicitly declared static. This includes anonymous and local
* classes.
*/
class InnerClass extends NestedClass {
InnerClass() { not this.isStatic() }
Expand Down
10 changes: 2 additions & 8 deletions java/ql/src/semmle/code/java/frameworks/play/Play.qll
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,8 @@ class PlayAddCsrfTokenAnnotation extends Annotation {
/**
* The type `play.libs.F.Promise<Result>`.
*/
class PlayAsyncResultPromise extends Member {
PlayAsyncResultPromise() {
exists(Class c |
c.hasQualifiedName("play.libs", "F") and
this = c.getAMember() and
this.getQualifiedName() = "F.Promise<Result>"
)
}
class PlayAsyncResultPromise extends MemberType {
PlayAsyncResultPromise() { hasQualifiedName("play.libs", "F$Promise<Result>") }
}

/**
Expand Down