public void endVisit(Variable variable) {
   if (variable.getParent().getType() != ASTNode.FIELD_ACCESS
       || (variable.getParent().getType() == ASTNode.FIELD_ACCESS
           && ((FieldAccess) variable.getParent()).getDispatcher() == variable)) {
     Expression varName = variable.getName();
     if (params.contains(((Identifier) varName).getName())
         && varName instanceof Identifier
         && variable.isDollared()
         && variable.getParent().getType() != ASTNode.STATIC_FIELD_ACCESS) {
       highlight(variable);
     }
   }
 }
  private static boolean checkGlobalVariable(Variable locateNode) {
    assert locateNode.getType() == ASTNode.VARIABLE;

    if (locateNode.getParent().getType() == ASTNode.STATIC_FIELD_ACCESS) {
      return false;
    }
    return locateNode.getParent().getType() == ASTNode.GLOBAL_STATEMENT // Global
        // $a
        // case
        || (locateNode.getEnclosingBodyNode() != null
            && locateNode.getEnclosingBodyNode().getType() == ASTNode.PROGRAM); // $a
    // declared
    // in
    // global
    // scope
    // case
  }
  private static boolean isLocalVariable(ASTNode locateNode) {
    assert locateNode != null;
    Variable parent = null;
    // check if it is an identifier
    if (locateNode instanceof Identifier
        && ((Identifier) locateNode).getParent() instanceof Variable) {
      parent = (Variable) ((Identifier) locateNode).getParent();
    } else if (locateNode.getType() == ASTNode.VARIABLE) {
      parent = (Variable) locateNode;
    } else {
      return false;
    }

    // check for not variables / or $this / or field declaration
    if (!parent.isDollared()
        || isThisVariable(parent)
        || parent.getType() == ASTNode.FIELD_DECLARATION) {
      return false;
    }

    // check for static variables
    if (parent.isDollared()
        && parent.getParent() != null
        && parent.getParent().getType() == ASTNode.STATIC_FIELD_ACCESS) {
      return false;
    }

    // check for static array variables
    if (parent.isDollared()
        && parent.getParent() != null
        && parent.getParent().getType() == ASTNode.ARRAY_ACCESS
        && parent != ((ArrayAccess) parent.getParent()).getIndex()
        && parent.getParent().getParent().getType() == ASTNode.STATIC_FIELD_ACCESS) {
      return false;
    }
    ASTNode node = parent;
    while (node != null) {
      final int type = node.getType();
      if (type == ASTNode.FUNCTION_DECLARATION) {
        return true;
      }
      node = node.getParent();
    }
    return false;
  }
  private static boolean checkGlobalIdentifier(ASTNode locateNode) {
    // check if it is a GLOBALS['a'] direction
    if (locateNode.getType() == ASTNode.SCALAR) {
      Scalar scalar = (Scalar) locateNode;
      return checkGLOBALS(scalar);
    }

    // check if it is an identifier
    if (locateNode.getType() != ASTNode.IDENTIFIER) {
      return false;
    }

    final Identifier targetIdentifier = ((Identifier) locateNode);

    ASTNode parent = locateNode.getParent();
    if (parent == null || parent.getType() != ASTNode.VARIABLE) {
      return false;
    }

    final Variable variable = (Variable) parent;
    // if it is not a dollared variable - it is not a global one
    if (!variable.isDollared() || variable.getParent().getType() == ASTNode.FIELD_DECLARATION) {
      return false;
    }

    // ignore static memeber call
    if (parent.getParent().getType() == ASTNode.STATIC_FIELD_ACCESS) {
      final StaticFieldAccess staticFieldAccess = (StaticFieldAccess) parent.getParent();
      if (staticFieldAccess.getMember() == variable) {
        return false;
      }
    }

    if (parent.getParent().getLocationInParent() == FieldsDeclaration.FIELDS_PROPERTY) {
      return false;
    }

    // check if declared global in function
    while (parent != null) {
      // if the variable was used inside a function
      if (parent.getType() == ASTNode.FUNCTION_DECLARATION) {
        // global declaration detection
        final int end = parent.getEnd();
        class GlobalSeacher extends ApplyAll {
          public int offset = end;

          public boolean apply(ASTNode node) {
            if (offset != end) {
              return false;
            }

            if (node.getType() == ASTNode.GLOBAL_STATEMENT) {
              GlobalStatement globalStatement = (GlobalStatement) node;
              if (checkGlobal(targetIdentifier, globalStatement)) {
                offset = globalStatement.getStart();
              }
            }

            return true;
          }
        }
        GlobalSeacher searchGlobal = new GlobalSeacher();
        parent.accept(searchGlobal);
        return searchGlobal.offset <= targetIdentifier.getStart();
      }
      parent = parent.getParent();
    }
    return true;
  }