Files
codeql/java/ql/lib/semmle/code/java/Element.qll
Chris Smowton 34a0a0d080 Implement $default method synthesis
This adds methods that fill in default parameters whenever a constructor or method uses default parameter values. I use as similar an approach to the real Kotlin compiler as possible both because this produces the desirable dataflow, and because it should merge cleanly with the same class file seen by the Java extractor, which will see and
extract the signatures of the default methods.
2022-10-06 12:38:55 +01:00

98 lines
3.0 KiB
Plaintext

/**
* Provides a class that represents named elements in Java programs.
*/
import CompilationUnit
import semmle.code.Location
import Javadoc
/** A program element that has a name. */
class Element extends @element, Top {
/** Holds if this element has the specified `name`. */
predicate hasName(string name) { hasName(this, name) }
/** Gets the name of this element. */
string getName() { this.hasName(result) }
/**
* Holds if this element transitively contains the specified element `e`.
*/
predicate contains(Element e) { this.hasChildElement+(e) }
/**
* Holds if this element is the immediate parent of the specified element `e`.
*
* It is usually preferable to use more specific predicates such as
* `getEnclosingCallable()`, `getDeclaringType()` and/or `getEnclosingType()`
* instead of this general predicate.
*/
predicate hasChildElement(Element e) { hasChildElement(this, e) }
/**
* Holds if this element pertains to a source file.
*
* Elements pertaining to source files may include generated elements
* not visible in source code, such as implicit default constructors.
*/
predicate fromSource() { this.getCompilationUnit().isSourceFile() }
/** Gets the compilation unit that this element belongs to. */
CompilationUnit getCompilationUnit() { result = this.getFile() }
/** Cast this element to a `Documentable`. */
Documentable getDoc() { result = this }
/** Holds if this is an auxiliary program element generated by the compiler. */
predicate isCompilerGenerated() { compiler_generated(this, _) }
/** Gets the reason this element was generated by the compiler, if any. */
string compilerGeneratedReason() {
exists(int i | compiler_generated(this, i) |
i = 1 and result = "Declaring classes of adapter functions in Kotlin"
or
i = 2 and result = "Generated data class member"
or
i = 3 and result = "Default property accessor"
or
i = 4 and result = "Class initialisation method <clinit>"
or
i = 5 and result = "Enum class special member"
or
i = 6 and result = "Getter for a Kotlin delegated property"
or
i = 7 and result = "Setter for a Kotlin delegated property"
or
i = 8 and result = "Proxy static method for a @JvmStatic-annotated function or property"
or
i = 9 and result = "Forwarder for a @JvmOverloads-annotated function"
or
i = 10 and result = "Forwarder for Kotlin calls that need default arguments filling in"
)
}
}
/**
* Holds if element `parent` is immediately above element `e` in the syntax tree.
*/
private predicate hasChildElement(Element parent, Element e) {
cupackage(e, parent)
or
enclInReftype(e, parent)
or
not enclInReftype(e, _) and
e.(Class).getCompilationUnit() = parent
or
not enclInReftype(e, _) and
e.(Interface).getCompilationUnit() = parent
or
methods(e, _, _, _, parent, _)
or
constrs(e, _, _, _, parent, _)
or
params(e, _, _, parent, _)
or
fields(e, _, _, parent, _)
or
typeVars(e, _, _, _, parent)
}