Files
codeql/java/ql/lib/definitions.qll
Andrew Eisenberg a3f4d1bf66 Move contextual queries from src to lib
With this change, users are now able to run View AST command in
vscode within vscode workspaces that do not include the core libraries.
The relevant core library only needs to be installed in the package
cache.
2022-06-29 07:51:26 -07:00

206 lines
6.6 KiB
Plaintext

/**
* Provides classes and predicates related to jump-to-definition links
* in the code viewer.
*/
import java
import IDEContextual
/**
* Restricts the location of a method access to the method identifier only,
* excluding its qualifier, type arguments and arguments.
*
* If there is any whitespace between the method identifier and its first argument,
* or between the method identifier and its qualifier (or last type argument, if any),
* the location may be slightly inaccurate and include such whitespace,
* but it should suffice for the purpose of avoiding overlapping definitions.
*/
private class LocationOverridingMethodAccess extends MethodAccess {
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
exists(MemberRefExpr e | e.getReferencedCallable() = getMethod() |
exists(int elRef, int ecRef | e.hasLocationInfo(path, _, _, elRef, ecRef) |
sl = elRef and
sc = ecRef - getMethod().getName().length() + 1 and
el = elRef and
ec = ecRef
)
)
or
not exists(MemberRefExpr e | e.getReferencedCallable() = getMethod()) and
exists(int slSuper, int scSuper, int elSuper, int ecSuper |
super.hasLocationInfo(path, slSuper, scSuper, elSuper, ecSuper)
|
(
if exists(getTypeArgument(_))
then
exists(Location locTypeArg |
locTypeArg = getTypeArgument(count(getTypeArgument(_)) - 1).getLocation()
|
sl = locTypeArg.getEndLine() and
sc = locTypeArg.getEndColumn() + 2
)
else (
if exists(getQualifier())
then
// Note: this needs to be the original (full) location of the qualifier, not the modified one.
exists(Location locQual | locQual = getQualifier().getLocation() |
sl = locQual.getEndLine() and
sc = locQual.getEndColumn() + 2
)
else (
sl = slSuper and
sc = scSuper
)
)
) and
(
if getNumArgument() > 0
then
// Note: this needs to be the original (full) location of the first argument, not the modified one.
exists(Location locArg | locArg = getArgument(0).getLocation() |
el = locArg.getStartLine() and
ec = locArg.getStartColumn() - 2
)
else (
el = elSuper and
ec = ecSuper - 2
)
)
)
}
}
/**
* Restricts the location of a type access to exclude
* the type arguments and qualifier, if any.
*/
private class LocationOverridingTypeAccess extends TypeAccess {
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
exists(int slSuper, int scSuper, int elSuper, int ecSuper |
super.hasLocationInfo(path, slSuper, scSuper, elSuper, ecSuper)
|
(
if exists(getQualifier())
then
// Note: this needs to be the original (full) location of the qualifier, not the modified one.
exists(Location locQual | locQual = getQualifier().getLocation() |
sl = locQual.getEndLine() and
sc = locQual.getEndColumn() + 2
)
else (
sl = slSuper and
sc = scSuper
)
) and
(
if exists(getTypeArgument(_))
then
// Note: this needs to be the original (full) location of the first type argument, not the modified one.
exists(Location locArg | locArg = getTypeArgument(0).getLocation() |
el = locArg.getStartLine() and
ec = locArg.getStartColumn() - 2
)
else (
el = elSuper and
ec = ecSuper
)
)
)
}
}
/**
* Restricts the location of a field access to the name of the accessed field only,
* excluding its qualifier.
*/
private class LocationOverridingFieldAccess extends FieldAccess {
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
super.hasLocationInfo(path, _, _, el, ec) and
sl = el and
sc = ec - getField().getName().length() + 1
}
}
/**
* Restricts the location of a single-type-import declaration to the name of the imported type only,
* excluding the `import` keyword and the package name.
*/
private class LocationOverridingImportType extends ImportType {
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
exists(int slSuper, int scSuper, int elSuper, int ecSuper |
super.hasLocationInfo(path, slSuper, scSuper, elSuper, ecSuper)
|
el = elSuper and
ec = ecSuper - 1 and
sl = el and
sc = ecSuper - getImportedType().getName().length()
)
}
}
/**
* Restricts the location of a single-static-import declaration to the name of the imported member(s) only,
* excluding the `import` keyword and the package name.
*/
private class LocationOverridingImportStaticTypeMember extends ImportStaticTypeMember {
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
exists(int slSuper, int scSuper, int elSuper, int ecSuper |
super.hasLocationInfo(path, slSuper, scSuper, elSuper, ecSuper)
|
el = elSuper and
ec = ecSuper - 1 and
sl = el and
sc = ecSuper - getName().length()
)
}
}
private Element definition(Element e, string kind) {
e.(MethodAccess).getMethod().getSourceDeclaration() = result and
kind = "M" and
not result instanceof InitializerMethod
or
e.(TypeAccess).getType().(RefType).getSourceDeclaration() = result and kind = "T"
or
exists(Variable v | v = e.(VarAccess).getVariable() |
result = v.(Field).getSourceDeclaration() or
result = v.(Parameter).getSourceDeclaration() or
result = v.(LocalVariableDecl)
) and
kind = "V"
or
e.(ImportType).getImportedType() = result and kind = "I"
or
e.(ImportStaticTypeMember).getAMemberImport() = result and kind = "I"
}
private predicate dummyVarAccess(VarAccess va) {
exists(AssignExpr ae, InitializerMethod im |
ae.getDest() = va and
ae.getParent() = im.getBody().getAChild()
)
}
private predicate dummyTypeAccess(TypeAccess ta) {
exists(FunctionalExpr e |
e.getAnonymousClass().getClassInstanceExpr().getTypeName() = ta.getParent*()
)
}
/**
* Gets an element, of kind `kind`, that element `e` uses, if any.
*
* The `kind` is a string representing what kind of use it is:
* - `"M"` for function and method calls
* - `"T"` for uses of types
* - `"V"` for variable accesses
* - `"I"` for import directives
*/
Element definitionOf(Element e, string kind) {
result = definition(e, kind) and
result.fromSource() and
e.fromSource() and
not dummyVarAccess(e) and
not dummyTypeAccess(e)
}