mirror of
https://github.com/github/codeql.git
synced 2025-12-18 18:10:39 +01:00
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.
206 lines
6.6 KiB
Plaintext
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)
|
|
}
|