[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/github/codeql/codeql-cli/v2.19.2/java/ql/lib/definitions.qll [Back]  [Original]

/**
 * 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)
}

Web Proxy Viewer  |  New URL  |  Original Page