diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index cafffae52bd..282d90eaeee 100644 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -2704,13 +2704,4 @@ 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)) -} +private class DiscardableExpr extends DiscardableLocatable, @expr { } diff --git a/java/ql/lib/semmle/code/java/Javadoc.qll b/java/ql/lib/semmle/code/java/Javadoc.qll index 101bab2723e..ac7a3c2cd6a 100644 --- a/java/ql/lib/semmle/code/java/Javadoc.qll +++ b/java/ql/lib/semmle/code/java/Javadoc.qll @@ -199,13 +199,4 @@ class KtCommentSection extends @ktcommentsection { } 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)) -} +private class DiscardableJavadoc extends DiscardableLocatable, @javadoc { } diff --git a/java/ql/lib/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll index 805ab0bf940..1e814117e9e 100644 --- a/java/ql/lib/semmle/code/java/Member.qll +++ b/java/ql/lib/semmle/code/java/Member.qll @@ -906,31 +906,11 @@ class ExtensionMethod extends Method { } 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)) +private class DiscardableAnonymousMethod extends DiscardableLocatable, @method { + DiscardableAnonymousMethod() { + exists(@classorinterface c | methods(this, _, _, _, c, _) and isAnonymClass(c, _)) + } } 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) - ) -} +private class DiscardableMethod extends DiscardableReferableLocatable, @method { } diff --git a/java/ql/lib/semmle/code/java/Overlay.qll b/java/ql/lib/semmle/code/java/Overlay.qll index 4ed0c185fb5..69178b1740a 100644 --- a/java/ql/lib/semmle/code/java/Overlay.qll +++ b/java/ql/lib/semmle/code/java/Overlay.qll @@ -35,3 +35,46 @@ predicate extractedInOverlay(string file) { // 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() + ) +} diff --git a/java/ql/lib/semmle/code/java/Statement.qll b/java/ql/lib/semmle/code/java/Statement.qll index d1e7e748bc3..a4872a32c91 100644 --- a/java/ql/lib/semmle/code/java/Statement.qll +++ b/java/ql/lib/semmle/code/java/Statement.qll @@ -990,13 +990,4 @@ class SuperConstructorInvocationStmt extends Stmt, ConstructorCall, @superconstr } 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)) -} +private class DiscardableStmt extends DiscardableLocatable, @stmt { } diff --git a/java/ql/lib/semmle/code/java/Variable.qll b/java/ql/lib/semmle/code/java/Variable.qll index 9b8b42b71fb..cb76fe3a9c9 100644 --- a/java/ql/lib/semmle/code/java/Variable.qll +++ b/java/ql/lib/semmle/code/java/Variable.qll @@ -136,13 +136,4 @@ class Parameter extends Element, @param, LocalScopeVariable { } 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)) -} +private class DiscardableLocalScopeVariable extends DiscardableLocatable, @localscopevariable { }