mirror of
https://github.com/github/codeql.git
synced 2026-05-01 11:45:14 +02:00
Java: Refactor definitions query, add queries for ide search
This enables jump-to-definition and find-references in the VS Code extension, for Java source archives.
This commit is contained in:
@@ -6,194 +6,8 @@
|
||||
* @id java/jump-to-definition
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
predicate dummyVarAccess(VarAccess va) {
|
||||
exists(AssignExpr ae, InitializerMethod im |
|
||||
ae.getDest() = va and
|
||||
ae.getParent() = im.getBody().getAChild()
|
||||
)
|
||||
}
|
||||
|
||||
predicate dummyTypeAccess(TypeAccess ta) {
|
||||
exists(FunctionalExpr e |
|
||||
e.getAnonymousClass().getClassInstanceExpr().getTypeName() = ta.getParent*()
|
||||
)
|
||||
}
|
||||
import definitions
|
||||
|
||||
from Element e, Element def, string kind
|
||||
where
|
||||
def = definition(e, kind) and
|
||||
def.fromSource() and
|
||||
e.fromSource() and
|
||||
not dummyVarAccess(e) and
|
||||
not dummyTypeAccess(e)
|
||||
where def = definitionOf(e, kind)
|
||||
select e, def, kind
|
||||
|
||||
Reference in New Issue
Block a user