Files
codeql/java/ql/lib/semmle/code/java/Modifier.qll
2022-10-05 15:25:49 +02:00

100 lines
3.8 KiB
Plaintext

/**
* Provides classes and predicates for working with Java modifiers.
*/
import Element
/** A modifier such as `private`, `static` or `abstract`. */
class Modifier extends Element, @modifier {
/** Gets the element to which this modifier applies. */
Element getElement() {
hasModifier(result, this) and
// Kotlin "internal" elements may also get "public" modifiers, so we want to filter those out
not exists(Modifier mod2 |
hasModifier(result, mod2) and modifiers(this, "public") and modifiers(mod2, "internal")
)
}
override string getAPrimaryQlClass() { result = "Modifier" }
}
/** An element of the Java syntax tree that may have a modifier. */
abstract class Modifiable extends Element {
/**
* Holds if this element has modifier `m`.
*
* For most purposes, the more specialized predicates `isAbstract`, `isPublic`, etc.
* should be used.
*
* Those specialized predicates also take implicit modifiers into account.
* For instance, non-default instance methods in interfaces are implicitly
* abstract, so `isAbstract()` will hold for them even if `hasModifier("abstract")`
* does not.
*/
predicate hasModifier(string m) { modifiers(this.getAModifier(), m) }
/** Holds if this element has no modifier. */
predicate hasNoModifier() { not hasModifier(this, _) }
/** Gets a modifier of this element. */
Modifier getAModifier() { this = result.getElement() }
/** Holds if this element has an `abstract` modifier or is implicitly abstract. */
predicate isAbstract() { this.hasModifier("abstract") }
/** Holds if this element has a `static` modifier or is implicitly static. */
predicate isStatic() { this.hasModifier("static") }
/** Holds if this element has a `final` modifier or is implicitly final. */
predicate isFinal() { this.hasModifier("final") }
/** Holds if this element has a `sealed` modifier. */
// TODO: `isSealed()` conflicts with `ClassOrInterface.isSealed()`. What name do we want to use here?
predicate isSealedKotlin() { this.hasModifier("sealed") }
/** Holds if this element has a `public` modifier or is implicitly public. */
predicate isPublic() { this.hasModifier("public") }
/** Holds if this element has a `protected` modifier. */
predicate isProtected() { this.hasModifier("protected") }
/** Holds if this element has a `private` modifier or is implicitly private. */
predicate isPrivate() { this.hasModifier("private") }
/** Holds if this element has an `internal` modifier. */
predicate isInternal() { this.hasModifier("internal") }
/** Holds if this element has an `inline` modifier. */
predicate isInline() { this.hasModifier("inline") }
/** Holds if this element has a `noinline` modifier. */
predicate isNoinline() { this.hasModifier("noinline") }
/** Holds if this element has a `crossinline` modifier. */
predicate isCrossinline() { this.hasModifier("crossinline") }
/** Holds if this element has a `suspend` modifier. */
predicate isSuspend() { this.hasModifier("suspend") }
/** Holds if this element has a `volatile` modifier. */
predicate isVolatile() { this.hasModifier("volatile") }
/** Holds if this element has a `synchronized` modifier. */
predicate isSynchronized() { this.hasModifier("synchronized") }
/** Holds if this element has a `native` modifier. */
predicate isNative() { this.hasModifier("native") }
/** Holds if this element has a `default` modifier. */
predicate isDefault() { this.hasModifier("default") }
/** Holds if this element has a `transient` modifier. */
predicate isTransient() { this.hasModifier("transient") }
/** Holds if this element has a `strictfp` modifier. */
predicate isStrictfp() { this.hasModifier("strictfp") }
/** Holds if this element has a `lateinit` modifier. */
predicate isLateinit() { this.hasModifier("lateinit") }
}