mirror of
https://github.com/github/codeql.git
synced 2026-03-05 07:06:47 +01:00
Merge pull request #19813 from github/kaspersv/overlay-java-discarding
Overlay: Add manual Java overlay annotations & discard predicates
This commit is contained in:
@@ -7,6 +7,7 @@ module;
|
||||
import java
|
||||
private import semmle.code.java.frameworks.android.Compose
|
||||
private import semmle.code.java.Constants
|
||||
private import semmle.code.java.Overlay
|
||||
|
||||
/** A common super-class that represents all kinds of expressions. */
|
||||
class Expr extends ExprParent, @expr {
|
||||
@@ -2701,3 +2702,6 @@ class RecordPatternExpr extends Expr, @recordpatternexpr {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
overlay[local]
|
||||
private class DiscardableExpr extends DiscardableLocatable, @expr { }
|
||||
|
||||
@@ -5,6 +5,7 @@ overlay[local?]
|
||||
module;
|
||||
|
||||
import semmle.code.Location
|
||||
private import semmle.code.java.Overlay
|
||||
|
||||
/** A Javadoc parent is an element whose child can be some Javadoc documentation. */
|
||||
class JavadocParent extends @javadocParent, Top {
|
||||
@@ -196,3 +197,6 @@ class KtCommentSection extends @ktcommentsection {
|
||||
/** Gets the string representation of this section. */
|
||||
string toString() { result = this.getContent() }
|
||||
}
|
||||
|
||||
overlay[local]
|
||||
private class DiscardableJavadoc extends DiscardableLocatable, @javadoc { }
|
||||
|
||||
@@ -11,6 +11,7 @@ import Annotation
|
||||
import Exception
|
||||
import metrics.MetricField
|
||||
private import dispatch.VirtualDispatch
|
||||
private import semmle.code.java.Overlay
|
||||
|
||||
/**
|
||||
* A common abstraction for type member declarations,
|
||||
@@ -623,7 +624,13 @@ class SrcMethod extends Method {
|
||||
then implementsInterfaceMethod(result, this)
|
||||
else result.getASourceOverriddenMethod*() = this
|
||||
) and
|
||||
(exists(result.getBody()) or result.hasModifier("native"))
|
||||
(
|
||||
// We allow empty method bodies for the local overlay variant to allow
|
||||
// calls to methods only fully extracted in base.
|
||||
isOverlay() or
|
||||
exists(result.getBody()) or
|
||||
result.hasModifier("native")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -897,3 +904,13 @@ class ExtensionMethod extends Method {
|
||||
else result = 0
|
||||
}
|
||||
}
|
||||
|
||||
overlay[local]
|
||||
private class DiscardableAnonymousMethod extends DiscardableLocatable, @method {
|
||||
DiscardableAnonymousMethod() {
|
||||
exists(@classorinterface c | methods(this, _, _, _, c, _) and isAnonymClass(c, _))
|
||||
}
|
||||
}
|
||||
|
||||
overlay[local]
|
||||
private class DiscardableMethod extends DiscardableReferableLocatable, @method { }
|
||||
|
||||
83
java/ql/lib/semmle/code/java/Overlay.qll
Normal file
83
java/ql/lib/semmle/code/java/Overlay.qll
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Defines entity discard predicates for Java overlay analysis.
|
||||
*/
|
||||
overlay[local?]
|
||||
module;
|
||||
|
||||
import java
|
||||
|
||||
/**
|
||||
* A local predicate that always holds for the overlay variant and
|
||||
* never holds for the base variant. This is used to define local
|
||||
* predicates that behave differently for the base and overlay variant.
|
||||
*/
|
||||
overlay[local]
|
||||
predicate isOverlay() { databaseMetadata("isOverlay", "true") }
|
||||
|
||||
/** Gets the raw file for a locatable. */
|
||||
overlay[local]
|
||||
string getRawFile(@locatable el) {
|
||||
exists(@location loc, @file file |
|
||||
hasLocation(el, loc) and
|
||||
locations_default(loc, file, _, _, _, _) and
|
||||
files(file, result)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the raw file for a location. */
|
||||
overlay[local]
|
||||
string getRawFileForLoc(@location l) {
|
||||
exists(@file f | locations_default(l, f, _, _, _, _) and files(f, result))
|
||||
}
|
||||
|
||||
/** Holds for files fully extracted in the overlay. */
|
||||
overlay[local]
|
||||
predicate extractedInOverlay(string file) {
|
||||
isOverlay() and
|
||||
// numlines is used to restrict attention to fully extracted files and
|
||||
// ignore skeleton extracted files in the overlay
|
||||
exists(@locatable l | numlines(l, _, _, _) and file = getRawFile(l))
|
||||
}
|
||||
|
||||
/**
|
||||
* A `@locatable` that should be discarded in the base variant if its file is
|
||||
* extracted in the overlay variant.
|
||||
*/
|
||||
overlay[local]
|
||||
abstract class DiscardableLocatable extends @locatable {
|
||||
/** Gets the raw file for a locatable in base. */
|
||||
string getRawFileInBase() { not isOverlay() and result = getRawFile(this) }
|
||||
|
||||
/** Gets a textual representation of this discardable locatable. */
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
overlay[discard_entity]
|
||||
private predicate discardLocatable(@locatable el) {
|
||||
extractedInOverlay(el.(DiscardableLocatable).getRawFileInBase())
|
||||
}
|
||||
|
||||
/**
|
||||
* A `@locatable` that should be discarded in the base variant if its file is
|
||||
* extracted in the overlay variant and it is itself not extracted in the
|
||||
* overlay, that is, it is deleted in the overlay.
|
||||
*/
|
||||
overlay[local]
|
||||
abstract class DiscardableReferableLocatable extends @locatable {
|
||||
/** Gets the raw file for a locatable in base. */
|
||||
string getRawFileInBase() { not isOverlay() and result = getRawFile(this) }
|
||||
|
||||
/** Holds if the locatable exists in the overlay. */
|
||||
predicate existsInOverlay() { isOverlay() and exists(this) }
|
||||
|
||||
/** Gets a textual representation of this discardable locatable. */
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
overlay[discard_entity]
|
||||
private predicate discardReferableLocatable(@locatable el) {
|
||||
exists(DiscardableReferableLocatable drl | drl = el |
|
||||
extractedInOverlay(drl.getRawFileInBase()) and
|
||||
not drl.existsInOverlay()
|
||||
)
|
||||
}
|
||||
@@ -6,6 +6,7 @@ module;
|
||||
|
||||
import Expr
|
||||
import metrics.MetricStmt
|
||||
private import semmle.code.java.Overlay
|
||||
|
||||
/** A common super-class of all statements. */
|
||||
class Stmt extends StmtParent, ExprParent, @stmt {
|
||||
@@ -987,3 +988,6 @@ class SuperConstructorInvocationStmt extends Stmt, ConstructorCall, @superconstr
|
||||
|
||||
override string getAPrimaryQlClass() { result = "SuperConstructorInvocationStmt" }
|
||||
}
|
||||
|
||||
overlay[local]
|
||||
private class DiscardableStmt extends DiscardableLocatable, @stmt { }
|
||||
|
||||
@@ -5,6 +5,7 @@ overlay[local?]
|
||||
module;
|
||||
|
||||
import Element
|
||||
private import semmle.code.java.Overlay
|
||||
|
||||
/** A variable is a field, a local variable or a parameter. */
|
||||
class Variable extends @variable, Annotatable, Element, Modifiable {
|
||||
@@ -133,3 +134,6 @@ class Parameter extends Element, @param, LocalScopeVariable {
|
||||
/** Holds if this is an anonymous parameter, `_` */
|
||||
predicate isAnonymous() { this.getName() = "" }
|
||||
}
|
||||
|
||||
overlay[local]
|
||||
private class DiscardableLocalScopeVariable extends DiscardableLocatable, @localscopevariable { }
|
||||
|
||||
Reference in New Issue
Block a user