public boolean visit(ForEachStatement foreachStatement) throws Exception {
   if (foreachStatement.getKey() instanceof VariableReference) {
     final SimpleReference var = (SimpleReference) foreachStatement.getKey();
     final ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
     info.modifiers = Modifiers.AccPublic;
     info.name = var.getName();
     info.nameSourceEnd = var.sourceEnd() - 1;
     info.nameSourceStart = var.sourceStart();
     info.declarationStart = var.sourceStart();
     fRequestor.enterField(info);
     fRequestor.exitField(var.sourceEnd() - 1);
   }
   if (foreachStatement.getValue() instanceof VariableReference) {
     final SimpleReference var = (SimpleReference) foreachStatement.getValue();
     final ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
     info.modifiers = Modifiers.AccPublic;
     info.name = var.getName();
     info.nameSourceEnd = var.sourceEnd() - 1;
     info.nameSourceStart = var.sourceStart();
     info.declarationStart = var.sourceStart();
     fRequestor.enterField(info);
     fRequestor.exitField(var.sourceEnd() - 1);
   }
   return true;
 }
  public boolean visit(Assignment assignment) throws Exception {
    Expression left = assignment.getVariable();
    if (left instanceof FieldAccess) { // class variable ($this->a = .)
      FieldAccess fieldAccess = (FieldAccess) left;
      Expression dispatcher = fieldAccess.getDispatcher();
      if (dispatcher instanceof VariableReference
          && "$this" //$NON-NLS-1$
              .equals(((VariableReference) dispatcher).getName())) {
        Expression field = fieldAccess.getField();
        if (field instanceof SimpleReference) {
          SimpleReference ref = (SimpleReference) field;
          ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
          info.modifiers = Modifiers.AccPublic;
          info.name = '$' + ref.getName();
          info.nameSourceEnd = ref.sourceEnd() - 1;
          info.nameSourceStart = ref.sourceStart();
          info.declarationStart = assignment.sourceStart();
          fInfoStack.push(info);
          fRequestor.enterField(info);
          fNodes.push(assignment);
        }
      }
    } else if (left instanceof VariableReference && !(left instanceof ArrayVariableReference)) {
      if (!declarations.empty()) {
        ASTNode parentDeclaration = declarations.peek();
        if (parentDeclaration instanceof MethodDeclaration
                && methodGlobalVars.peek().contains(((VariableReference) left).getName())
            || parentDeclaration == fLastNamespace) {
          deferredDeclarations.add(assignment);
          return false;
        }
      }
      if (!fInfoStack.isEmpty() && fInfoStack.peek() instanceof ISourceElementRequestor.FieldInfo) {
        if (!fDeferredVariables.containsKey(fInfoStack.peek())) {
          fDeferredVariables.put(fInfoStack.peek(), new LinkedList<Assignment>());
        }
        fDeferredVariables.get(fInfoStack.peek()).add(assignment);
        return false;
      }
      ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
      info.modifiers = Modifiers.AccPublic;
      info.name = ((VariableReference) left).getName();
      info.nameSourceEnd = left.sourceEnd() - 1;
      info.nameSourceStart = left.sourceStart();
      info.declarationStart = assignment.sourceStart();

      fInfoStack.push(info);
      if (assignment.getOperatorType() == Assignment.OP_EQUAL) {
        fRequestor.enterField(info);
      } else {
        ISourceElementRequestor sourceElementRequestor = (ISourceElementRequestor) fRequestor;
        sourceElementRequestor.enterFieldCheckDuplicates(info);
      }
      fNodes.push(assignment);
    }
    return true;
  }
  public boolean visit(PHPFieldDeclaration declaration) throws Exception {
    // This is variable declaration:
    ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
    info.modifiers = declaration.getModifiers();
    info.name = declaration.getName();
    SimpleReference var = declaration.getRef();
    info.nameSourceEnd = var.sourceEnd() - 1;
    info.nameSourceStart = var.sourceStart();
    info.declarationStart = declaration.getDeclarationStart();
    info.modifiers = markAsDeprecated(info.modifiers, declaration);
    PHPDocBlock doc = declaration.getPHPDoc();
    if (doc != null) {
      for (PHPDocTag tag : doc.getTags(PHPDocTag.VAR)) {
        // do it like for
        // PHPDocumentationContentAccess#handleBlockTags(List tags):
        // variable name can be optional, but if present keep only
        // the good ones
        if (tag.getVariableReference() != null
            && !tag.getVariableReference().getName().equals(declaration.getName())) {
          continue;
        }

        if (tag.getTypeReferences().size() > 0) {
          info.type = PHPModelUtils.appendTypeReferenceNames(tag.getTypeReferences());
          break;
        }
      }
    }
    fInfoStack.push(info);
    fRequestor.enterField(info);
    return true;
  }
  public boolean visit(Assignment assignment) throws Exception {
    final Expression left = assignment.getVariable();
    if (left instanceof FieldAccess) { // class variable ($this->a = .)
      final FieldAccess fieldAccess = (FieldAccess) left;
      final Expression dispatcher = fieldAccess.getDispatcher();
      if (dispatcher instanceof VariableReference
          && "$this".equals(((VariableReference) dispatcher).getName())) { // $NON-NLS-1$
        final Expression field = fieldAccess.getField();
        if (field instanceof SimpleReference) {
          final SimpleReference ref = (SimpleReference) field;
          final ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
          info.modifiers = Modifiers.AccPublic;
          info.name = '$' + ref.getName();
          info.nameSourceEnd = ref.sourceEnd() - 1;
          info.nameSourceStart = ref.sourceStart();
          info.declarationStart = assignment.sourceStart();
          fRequestor.enterField(info);
          fNodes.push(assignment);
        }
      }
    } else if (left instanceof VariableReference) {
      if (!declarations.empty()) {
        final Declaration parentDeclaration = declarations.peek();
        if (parentDeclaration instanceof MethodDeclaration
                && methodGlobalVars.peek().contains(((VariableReference) left).getName())
            || parentDeclaration == fLastNamespace) {
          deferredDeclarations.add(assignment);
          return false;
        }
      }

      final ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
      info.modifiers = Modifiers.AccPublic;
      info.name = ((VariableReference) left).getName();
      info.nameSourceEnd = left.sourceEnd() - 1;
      info.nameSourceStart = left.sourceStart();
      info.declarationStart = assignment.sourceStart();
      fRequestor.enterField(info);
      fNodes.push(assignment);
    }
    return true;
  }
 public boolean visit(ConstantDeclaration declaration) throws Exception {
   final ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
   info.modifiers = Modifiers.AccConstant | Modifiers.AccPublic | Modifiers.AccFinal;
   final ConstantReference constantName = declaration.getConstantName();
   info.name = ASTUtils.stripQuotes(constantName.getName());
   info.nameSourceEnd = constantName.sourceEnd() - 1;
   info.nameSourceStart = constantName.sourceStart();
   info.declarationStart = declaration.sourceStart();
   fRequestor.enterField(info);
   return true;
 }
 public boolean visit(CatchClause catchClause) throws Exception {
   final ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
   info.modifiers = Modifiers.AccPublic;
   final SimpleReference var = catchClause.getVariable();
   info.name = var.getName();
   info.nameSourceEnd = var.sourceEnd() - 1;
   info.nameSourceStart = var.sourceStart();
   info.declarationStart = catchClause.sourceStart();
   fRequestor.enterField(info);
   return true;
 }
  /**
   * Resolve class members that were defined using the @property tag
   *
   * @param type declaration for wich we add the magic variables
   */
  private void resolveMagicMembers(TypeDeclaration type) {
    if (type instanceof IPHPDocAwareDeclaration) {
      final IPHPDocAwareDeclaration declaration = (IPHPDocAwareDeclaration) type;
      final PHPDocBlock doc = declaration.getPHPDoc();
      if (doc != null) {
        final PHPDocTag[] tags = doc.getTags();
        for (final PHPDocTag docTag : tags) {
          final int tagKind = docTag.getTagKind();
          if (tagKind == PHPDocTag.PROPERTY
              || tagKind == PHPDocTag.PROPERTY_READ
              || tagKind == PHPDocTag.PROPERTY_WRITE) {
            // http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_tags.property.pkg.html
            final String[] split = WHITESPACE_SEPERATOR.split(docTag.getValue().trim());
            if (split.length < 2) {
              break;
            }
            final ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
            info.modifiers = Modifiers.AccPublic;
            info.name = split[1];
            final SimpleReference var =
                new SimpleReference(
                    docTag.sourceStart(), docTag.sourceStart() + 9, removeParenthesis(split));
            info.nameSourceStart = var.sourceStart();
            info.nameSourceEnd = var.sourceEnd();
            info.declarationStart = info.nameSourceStart;
            fRequestor.enterField(info);
            fRequestor.exitField(info.nameSourceEnd);

          } else if (tagKind == PHPDocTag.METHOD) {
            // http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_tags.method.pkg.html
            final String[] split = WHITESPACE_SEPERATOR.split(docTag.getValue().trim());
            if (split.length < 2) {
              break;
            }

            final ISourceElementRequestor.MethodInfo mi = new ISourceElementRequestor.MethodInfo();
            mi.parameterNames = null;
            mi.name = removeParenthesis(split);
            final SimpleReference var =
                new SimpleReference(
                    docTag.sourceStart(), docTag.sourceStart() + 6, removeParenthesis(split));
            mi.modifiers = Modifiers.AccPublic;
            mi.nameSourceStart = var.sourceStart();
            mi.nameSourceEnd = var.sourceEnd();
            mi.declarationStart = mi.nameSourceStart;
            mi.isConstructor = false;

            this.fRequestor.enterMethod(mi);
            this.fRequestor.exitMethod(mi.nameSourceEnd);
          }
        }
      }
    }
  }
 public boolean visit(FieldDeclaration declaration) throws Exception {
   // This is constant declaration:
   final ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
   info.modifiers = Modifiers.AccConstant | Modifiers.AccPublic | Modifiers.AccFinal;
   info.name = declaration.getName();
   info.nameSourceStart = declaration.getNameStart();
   info.nameSourceEnd = declaration.getNameEnd() - 1;
   info.declarationStart = declaration.sourceStart();
   fRequestor.enterField(info);
   fRequestor.exitField(declaration.sourceEnd() - 1);
   return true;
 }
  public boolean visit(MethodDeclaration method) throws Exception {

    methodGlobalVars.add(new HashSet<String>());

    ASTNode parentDeclaration = null;
    if (!declarations.empty()) {
      parentDeclaration = declarations.peek();
    }

    // In case we are entering a nested element - just add to the deferred
    // list
    // and get out of the nested element visiting process
    if (parentDeclaration instanceof MethodDeclaration) {
      if (fLastNamespace == null) {
        deferredDeclarations.add(method);
      } else {
        deferredNamespacedDeclarations.add(method);
      }
      return false;
    }

    if (parentDeclaration instanceof InterfaceDeclaration) {
      method.setModifier(Modifiers.AccAbstract);
    }

    method.setModifiers(markAsDeprecated(method.getModifiers(), method));

    declarations.push(method);

    for (PHPSourceElementRequestorExtension visitor : extensions) {
      visitor.visit(method);
    }

    boolean visit = visitMethodDeclaration(method);

    if (visit) {
      // Process method argument (local variable) declarations:
      List<Argument> arguments = method.getArguments();
      for (Argument arg : arguments) {
        ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
        info.name = arg.getName();
        info.modifiers = Modifiers.AccPublic;
        info.nameSourceStart = arg.getNameStart();
        info.nameSourceEnd = arg.getNameEnd() - 1;
        info.declarationStart = arg.sourceStart();
        fRequestor.enterField(info);
        fRequestor.exitField(arg.sourceEnd() - 1);
      }
    }
    return visit;
  }
  public boolean visit(ListVariable listVariable) throws Exception {
    final Collection<? extends Expression> variables = (listVariable).getVariables();
    for (final Expression expression : variables) {

      if (expression instanceof VariableReference) {
        final ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
        info.modifiers = Modifiers.AccPublic;
        info.name = ((VariableReference) expression).getName();
        info.nameSourceEnd = expression.sourceEnd() - 1;
        info.nameSourceStart = expression.sourceStart();
        info.declarationStart = expression.sourceStart();
        fRequestor.enterField(info);
        fRequestor.exitField(expression.sourceEnd() - 1);
      }
    }
    return true;
  }
 public boolean visit(PHPFieldDeclaration declaration) throws Exception {
   // This is variable declaration:
   final ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
   info.modifiers = declaration.getModifiers();
   info.name = declaration.getName();
   final SimpleReference var = declaration.getRef();
   info.nameSourceEnd = var.sourceEnd() - 1;
   info.nameSourceStart = var.sourceStart();
   info.declarationStart = declaration.getDeclarationStart();
   final PHPDocBlock doc = declaration.getPHPDoc();
   if (doc != null) {
     for (final PHPDocTag tag : doc.getTags(PHPDocTag.VAR)) {
       final SimpleReference[] references = tag.getReferences();
       if (references.length > 0) {
         info.type = PHPModelUtils.extractElementName(references[0].getName());
       }
     }
   }
   fRequestor.enterField(info);
   return true;
 }
  public boolean visit(LambdaFunctionDeclaration lambdaMethod) throws Exception {

    fNodes.push(lambdaMethod);
    methodGlobalVars.add(new HashSet<String>());

    // Declaration parentDeclaration = null;
    // if (!declarations.empty()
    // && declarations.peek() instanceof MethodDeclaration) {
    // parentDeclaration = declarations.peek();
    // // In case we are entering a nested element - just add to the
    // // deferred list and get out of the nested element visiting process
    // deferredDeclarations.add(lambdaMethod);
    // return visitGeneral(lambdaMethod);
    // }

    final Collection<FormalParameter> arguments = lambdaMethod.getArguments();
    final StringBuilder metadata = new StringBuilder();
    final String[] parameters = new String[arguments.size()];
    // if (arguments != null) {
    final Iterator<FormalParameter> i = arguments.iterator();
    int indx = 0;
    while (i.hasNext()) {
      final Argument arg = i.next();
      metadata.append(arg.getName());
      parameters[indx] = arg.getName();
      indx++;
      if (i.hasNext()) {
        metadata.append(",");
      }
    }
    // }

    // Add method declaration:
    for (final PHPSourceElementRequestorExtension visitor : extensions) {
      visitor.visit(lambdaMethod);
    }

    final ISourceElementRequestor.MethodInfo mi = new ISourceElementRequestor.MethodInfo();
    mi.parameterNames = parameters;
    mi.name = PHPCoreConstants.ANONYMOUS;
    mi.modifiers = Modifiers.AccPublic;
    mi.nameSourceStart = lambdaMethod.sourceStart();
    mi.nameSourceEnd = lambdaMethod.sourceEnd();
    mi.declarationStart = mi.nameSourceStart;
    mi.isConstructor = false;

    this.fRequestor.enterMethod(mi);
    this.fInMethod = true;

    for (final Argument arg : arguments) {
      final ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
      info.name = arg.getName();
      info.modifiers = Modifiers.AccPublic;
      info.nameSourceStart = arg.getNameStart();
      info.nameSourceEnd = arg.getNameEnd() - 1;
      info.declarationStart = arg.sourceStart();
      fRequestor.enterField(info);
      fRequestor.exitField(arg.sourceEnd() - 1);
    }

    return true;
  }
  /**
   * Resolve class members that were defined using the @property tag
   *
   * @param type declaration for wich we add the magic variables
   */
  private void resolveMagicMembers(TypeDeclaration type) {
    if (type instanceof IPHPDocAwareDeclaration) {
      IPHPDocAwareDeclaration declaration = (IPHPDocAwareDeclaration) type;
      final PHPDocBlock doc = declaration.getPHPDoc();
      if (doc != null) {
        Pattern WHITESPACE_SEPERATOR = MagicMemberUtil.WHITESPACE_SEPERATOR;
        final PHPDocTag[] tags = doc.getTags();
        for (PHPDocTag docTag : tags) {
          final int tagKind = docTag.getTagKind();
          if (tagKind == PHPDocTag.PROPERTY
              || tagKind == PHPDocTag.PROPERTY_READ
              || tagKind == PHPDocTag.PROPERTY_WRITE) {
            // http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_tags.property.pkg.html
            final String[] split = WHITESPACE_SEPERATOR.split(docTag.getValue().trim());
            if (split.length < 2) {
              continue;
            }
            ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
            info.modifiers = Modifiers.AccPublic | IPHPModifiers.AccMagicProperty;
            info.name = split[1];
            info.type = split[0];

            SimpleReference var =
                new SimpleReference(
                    docTag.sourceStart(), docTag.sourceStart() + 9, removeParenthesis(split));
            info.nameSourceStart = var.sourceStart();
            info.nameSourceEnd = var.sourceEnd();
            info.declarationStart = info.nameSourceStart;

            fRequestor.enterField(info);
            fRequestor.exitField(info.nameSourceEnd);

          } else if (tagKind == PHPDocTag.METHOD) {
            // http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_tags.method.pkg.html

            // workaround for lack of method return type
            int methodModifiers = Modifiers.AccPublic;
            String docTagValue = docTag.getValue().trim();
            int index = docTagValue.indexOf('(');
            if (index != -1) {
              String[] split = WHITESPACE_SEPERATOR.split(docTagValue.substring(0, index).trim());
              if (split.length == 1) {
                docTagValue =
                    new StringBuilder(VOID_RETURN_TYPE)
                        .append(Constants.SPACE)
                        .append(docTagValue)
                        .toString();
              } else if (split.length == 2 && Constants.STATIC.equals(split[0])) {
                StringBuilder sb = new StringBuilder(Constants.STATIC);
                sb.append(Constants.SPACE).append(VOID_RETURN_TYPE);
                sb.append(docTagValue.substring(6));
                docTagValue = sb.toString();
              }
            }
            String[] split = WHITESPACE_SEPERATOR.split(docTagValue);
            if (split.length < 2) {
              continue;
            }
            if (Constants.STATIC.equals(split[0])) {
              methodModifiers |= Modifiers.AccStatic;
              split = Arrays.copyOfRange(split, 1, split.length);
              docTagValue = docTagValue.substring(7).trim();
              if (split.length < 2) {
                continue;
              }
            }

            ISourceElementRequestor.MethodInfo mi = new ISourceElementRequestor.MethodInfo();
            mi.parameterNames = null;
            mi.name = removeParenthesis(split);
            SimpleReference var =
                new SimpleReference(
                    docTag.sourceStart(), docTag.sourceStart() + 6, removeParenthesis(split));
            mi.modifiers = methodModifiers;
            mi.nameSourceStart = var.sourceStart();
            mi.nameSourceEnd = var.sourceEnd();
            mi.declarationStart = mi.nameSourceStart;
            mi.isConstructor = false;
            mi.returnType = split[0];

            MagicMethod magicMethod;
            if (mi.name != null && mi.name.indexOf('(') > 0) {
              magicMethod = MagicMemberUtil.getMagicMethod2(docTagValue);
              mi.name = magicMethod.name;
            } else {
              magicMethod = MagicMemberUtil.getMagicMethod(docTagValue);
            }
            if (magicMethod != null) {
              mi.parameterNames = magicMethod.parameterNames;
              mi.parameterTypes = magicMethod.parameterTypes;
              mi.parameterInitializers = magicMethod.parameterInitializers;
            }

            this.fRequestor.enterMethod(mi);
            this.fRequestor.exitMethod(mi.nameSourceEnd);
          }
        }
      }
    }
  }