/**
   * Find first variable declaration in parent scope of a given variable:
   *
   * <p>function() { $event = new FooEvent(); dispatch('foo', $event); }
   */
  @Nullable
  public static String getFirstVariableTypeInScope(@NotNull Variable variable) {

    // parent search scope, eg Method else fallback to a grouped statement
    PsiElement searchScope = PsiTreeUtil.getParentOfType(variable, Function.class);
    if (searchScope == null) {
      searchScope = PsiTreeUtil.getParentOfType(variable, GroupStatement.class);
    }

    if (searchScope == null) {
      return null;
    }

    final String name = variable.getName();
    if (name == null) {
      return null;
    }

    final String[] result = {null};
    searchScope.acceptChildren(
        new PsiRecursiveElementVisitor() {
          @Override
          public void visitElement(PsiElement element) {
            if (element instanceof Variable && name.equals(((Variable) element).getName())) {
              PsiElement assignmentExpression = element.getParent();
              if (assignmentExpression instanceof AssignmentExpression) {
                PhpPsiElement value = ((AssignmentExpression) assignmentExpression).getValue();
                if (value instanceof NewExpression) {
                  ClassReference classReference = ((NewExpression) value).getClassReference();
                  if (classReference != null) {
                    String classSignature = classReference.getFQN();
                    if (StringUtils.isNotBlank(classSignature)) {
                      result[0] = classSignature;
                    }
                  }
                }
              }
            }

            super.visitElement(element);
          }
        });

    return result[0];
  }
 private void processEntry(
     @Nullable JavaElementArrangementEntry entry,
     @Nullable PsiModifierListOwner modifier,
     @Nullable PsiElement nextPsiRoot) {
   if (entry == null) {
     return;
   }
   if (modifier != null) {
     parseModifiers(modifier.getModifierList(), entry);
   }
   if (nextPsiRoot == null) {
     return;
   }
   myStack.push(entry);
   try {
     nextPsiRoot.acceptChildren(this);
   } finally {
     myStack.pop();
   }
 }
 @Override
 public void visitDeclarationStatement(PsiDeclarationStatement statement) {
   for (PsiElement element : statement.getDeclaredElements()) {
     element.acceptChildren(this);
   }
 }
 @Override
 public void visitElement(PsiElement element) {
   element.acceptChildren(this);
 }