зеркало из https://github.com/github/codeql.git
202 строки
6.6 KiB
Plaintext
202 строки
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 LocationOverridingMethodCall extends MethodCall {
|
|
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
|
exists(MemberRefExpr e | e.getReferencedCallable() = this.getMethod() |
|
|
exists(int elRef, int ecRef | e.hasLocationInfo(path, _, _, elRef, ecRef) |
|
|
sl = elRef and
|
|
sc = ecRef - this.getMethod().getName().length() + 1 and
|
|
el = elRef and
|
|
ec = ecRef
|
|
)
|
|
)
|
|
or
|
|
not exists(MemberRefExpr e | e.getReferencedCallable() = this.getMethod()) and
|
|
exists(int slSuper, int scSuper, int elSuper, int ecSuper |
|
|
super.hasLocationInfo(path, slSuper, scSuper, elSuper, ecSuper)
|
|
|
|
|
(
|
|
if exists(this.getTypeArgument(_))
|
|
then
|
|
exists(Location locTypeArg |
|
|
locTypeArg = this.getTypeArgument(count(this.getTypeArgument(_)) - 1).getLocation()
|
|
|
|
|
sl = locTypeArg.getEndLine() and
|
|
sc = locTypeArg.getEndColumn() + 2
|
|
)
|
|
else (
|
|
if exists(this.getQualifier())
|
|
then
|
|
// Note: this needs to be the original (full) location of the qualifier, not the modified one.
|
|
exists(Location locQual | locQual = this.getQualifier().getLocation() |
|
|
sl = locQual.getEndLine() and
|
|
sc = locQual.getEndColumn() + 2
|
|
)
|
|
else (
|
|
sl = slSuper and
|
|
sc = scSuper
|
|
)
|
|
)
|
|
) and
|
|
(
|
|
if this.getNumArgument() > 0
|
|
then
|
|
// Note: this needs to be the original (full) location of the first argument, not the modified one.
|
|
exists(Location locArg | locArg = this.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(this.getQualifier())
|
|
then
|
|
// Note: this needs to be the original (full) location of the qualifier, not the modified one.
|
|
exists(Location locQual | locQual = this.getQualifier().getLocation() |
|
|
sl = locQual.getEndLine() and
|
|
sc = locQual.getEndColumn() + 2
|
|
)
|
|
else (
|
|
sl = slSuper and
|
|
sc = scSuper
|
|
)
|
|
) and
|
|
(
|
|
if exists(this.getTypeArgument(_))
|
|
then
|
|
// Note: this needs to be the original (full) location of the first type argument, not the modified one.
|
|
exists(Location locArg | locArg = this.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 - this.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 elSuper, int ecSuper | super.hasLocationInfo(path, _, _, elSuper, ecSuper) |
|
|
el = elSuper and
|
|
ec = ecSuper - 1 and
|
|
sl = el and
|
|
sc = ecSuper - this.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 elSuper, int ecSuper | super.hasLocationInfo(path, _, _, elSuper, ecSuper) |
|
|
el = elSuper and
|
|
ec = ecSuper - 1 and
|
|
sl = el and
|
|
sc = ecSuper - this.getName().length()
|
|
)
|
|
}
|
|
}
|
|
|
|
private Element definition(Element e, string kind) {
|
|
e.(MethodCall).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) 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)
|
|
}
|