Java: Add entity discard predicates

This commit is contained in:
Kasper Svendsen
2025-01-09 09:35:56 +01:00
parent b6e56f26c7
commit 6e92d7e247
7 changed files with 134 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ module;
import FileSystem
import semmle.code.java.Element
private import semmle.code.java.Overlay
private import semmle.code.SMAP
/** Holds if element `e` has name `name`. */
@@ -221,3 +222,16 @@ private predicate fixedHasLocation(Top l, Location loc, File f) {
not hasSourceLocation(l, _, _) and
locations_default(loc, f, _, _, _, _)
}
overlay[local]
private predicate discardableLocation(string file, @location l) {
not isOverlay() and
file = getRawFileForLoc(l) and
not exists(@file f | hasLocation(f, l))
}
/** Discard base locations in files fully extracted in the overlay. */
overlay[discard_entity]
private predicate discardLocation(@location l) {
exists(string file | discardableLocation(file, l) and extractedInOverlay(file))
}

View File

@@ -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,15 @@ class RecordPatternExpr extends Expr, @recordpatternexpr {
)
}
}
overlay[local]
private predicate discardableExpr(string file, @expr e) {
not isOverlay() and
file = getRawFile(e)
}
/** Discard base expressions in files fully extracted in the overlay. */
overlay[discard_entity]
private predicate discardExpr(@expr e) {
exists(string file | discardableExpr(file, e) and extractedInOverlay(file))
}

View File

@@ -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,15 @@ class KtCommentSection extends @ktcommentsection {
/** Gets the string representation of this section. */
string toString() { result = this.getContent() }
}
overlay[local]
private predicate discardableJavadoc(string file, @javadoc d) {
not isOverlay() and
exists(@member m | file = getRawFile(m) and hasJavadoc(m, d))
}
/** Discard javadoc entities in files fully extracted in the overlay. */
overlay[discard_entity]
private predicate discardJavadoc(@javadoc d) {
exists(string file | discardableJavadoc(file, d) and extractedInOverlay(file))
}

View File

@@ -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,
@@ -897,3 +898,33 @@ class ExtensionMethod extends Method {
else result = 0
}
}
overlay[local]
private predicate discardableMethod(string file, @method m) {
not isOverlay() and
file = getRawFile(m) and
exists(@classorinterface c | methods(m, _, _, _, c, _) and isAnonymClass(c, _))
}
/** Discard base methods on anonymous classes in files fully extracted in the overlay. */
overlay[discard_entity]
private predicate discardAnonMethod(@method m) {
exists(string file | discardableMethod(file, m) and extractedInOverlay(file))
}
overlay[local]
private predicate discardableBaseMethod(string file, @method m) {
not isOverlay() and
file = getRawFile(m)
}
overlay[local]
private predicate usedOverlayMethod(@method m) { isOverlay() and methods(m, _, _, _, _, _) }
/** Discard base methods in files fully extracted in the overlay that were not extracted in the overlay. */
overlay[discard_entity]
private predicate discardMethod(@method m) {
exists(string file |
discardableBaseMethod(file, m) and extractedInOverlay(file) and not usedOverlayMethod(m)
)
}

View File

@@ -0,0 +1,37 @@
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))
}

View File

@@ -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,15 @@ class SuperConstructorInvocationStmt extends Stmt, ConstructorCall, @superconstr
override string getAPrimaryQlClass() { result = "SuperConstructorInvocationStmt" }
}
overlay[local]
private predicate discardableStmt(string file, @stmt s) {
not isOverlay() and
file = getRawFile(s)
}
/** Discard base statements in files fully extracted in the overlay. */
overlay[discard_entity]
private predicate discardStmt(@stmt s) {
exists(string file | discardableStmt(file, s) and extractedInOverlay(file))
}

View File

@@ -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,15 @@ class Parameter extends Element, @param, LocalScopeVariable {
/** Holds if this is an anonymous parameter, `_` */
predicate isAnonymous() { this.getName() = "" }
}
overlay[local]
private predicate discardableLocalVarDecl(string file, @localscopevariable l) {
not isOverlay() and
file = getRawFile(l)
}
/** Discard base local scoped variables in files fully extracted in the overlay. */
overlay[discard_entity]
private predicate discardLocalVarDecl(@localscopevariable l) {
exists(string file | discardableLocalVarDecl(file, l) and extractedInOverlay(file))
}