/**
   * 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) {
        for (PHPDocTag docTag : doc.getTags()) {
          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;
            }

            String name = removeParenthesis(split);
            int offset = docTag.sourceStart();
            int length = docTag.sourceStart() + 9;

            Map<String, String> info = new HashMap<String, String>();
            info.put("v", split[0]); // $NON-NLS-1$

            StringBuilder metadata = new StringBuilder();
            if (fCurrentQualifier != null) {
              metadata.append(fCurrentQualifierCounts.get(fCurrentQualifier));
              metadata.append(";"); // $NON-NLS-1$
            }

            modifyDeclaration(
                null,
                new DeclarationInfo(
                    IModelElement.FIELD,
                    Modifiers.AccPublic,
                    offset,
                    length,
                    offset,
                    length,
                    name,
                    metadata.length() == 0 ? null : metadata.toString(),
                    encodeDocInfo(info),
                    fCurrentQualifier,
                    fCurrentParent));

          } else if (tagKind == PHPDocTag.METHOD) {
            // http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_tags.method.pkg.html
            String[] split = WHITESPACE_SEPERATOR.split(docTag.getValue().trim());
            if (split.length < 2) {
              break;
            }
            int methodModifiers = Modifiers.AccPublic;
            if (Constants.STATIC.equals(split[0].trim())) {
              if (split.length < 3) {
                break;
              }
              methodModifiers |= Modifiers.AccStatic;
              split = Arrays.copyOfRange(split, 1, split.length);
            }

            String name = removeParenthesis(split);
            int index = name.indexOf('(');
            if (index > 0) {
              name = name.substring(0, index);
            }
            int offset = docTag.sourceStart();
            int length = docTag.sourceStart() + 6;
            Map<String, String> info = new HashMap<String, String>();
            info.put("r", split[0]); // $NON-NLS-1$

            StringBuilder metadata = new StringBuilder();
            if (fCurrentQualifier != null) {
              metadata.append(fCurrentQualifierCounts.get(fCurrentQualifier));
              metadata.append(";"); // $NON-NLS-1$
            }

            modifyDeclaration(
                null,
                new DeclarationInfo(
                    IModelElement.METHOD,
                    methodModifiers,
                    offset,
                    length,
                    offset,
                    length,
                    name,
                    metadata.length() == 0 ? null : metadata.toString(),
                    encodeDocInfo(info),
                    fCurrentQualifier,
                    fCurrentParent));
          }
        }
      }
    }
  }
  /**
   * 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);
          }
        }
      }
    }
  }