/**
   * Get Item from {@link IField} <br>
   * DLTK Model => AST
   */
  public static Item getItem(IField field) {
    IModelElement parent = field.getParent();
    if (parent instanceof IType) {
      RecordTypeDef typeDef = (RecordTypeDef) getTypeDef((IType) parent);
      return typeDef.getFields().get(field.getElementName());
    } else if (parent instanceof ISourceModule) {
      LuaSourceRoot luaSourceRoot = getLuaSourceRoot((ISourceModule) parent);
      try {
        if (Flags.isPrivate(field.getFlags())) {
          List<LocalVar> localVars = luaSourceRoot.getInternalContent().getContent().getLocalVars();
          for (LocalVar localVar : localVars) {
            if (localVar.getVar().getName().equals(field.getElementName()))
              return localVar.getVar();
          }
        } else {

          return luaSourceRoot.getFileapi().getGlobalvars().get(field.getElementName());
        }
      } catch (ModelException e) {
        Activator.logError("unable to get item from field " + field, e); // $NON-NLS-1$
        return null;
      }
    }
    return null;
  }
  @SuppressWarnings({"rawtypes", "unchecked"})
  private Map getFields() throws ModelException {

    IField[] fields = type.getFields();
    Map result = new LinkedHashMap();
    for (int i = 0; i < fields.length; i++) {

      IField field = fields[i];

      int flags = field.getFlags();
      if (PHPFlags.isStatic(flags) || PHPFlags.isConstant(flags)) {
        continue;
      }

      String name = field.getElementName().replace("$", "");
      String getter = "get" + name.toLowerCase();
      String setter = "set" + name.toLowerCase();

      List l = new ArrayList(2);
      List<GetterSetterEntry> entries = new ArrayList<GetterSetterEntry>();

      boolean getterExists = false;
      boolean setterExists = false;

      for (IMethod method : type.getMethods()) {
        String methodName = method.getElementName().toLowerCase();
        if (methodName.startsWith("get")) {
          getterExists = methodName.equals(getter);
        } else if (methodName.startsWith("set")) {
          setterExists = methodName.equals(setter);
        }
      }

      if (!getterExists) {
        entries.add(new GetterSetterEntry(field, true));
      }

      if (!setterExists) {
        entries.add(new GetterSetterEntry(field, false));
      }

      if (!getterExists || !setterExists) {
        l.addAll(entries);
      }

      if (!l.isEmpty()) result.put(field, l.toArray(new GetterSetterEntry[l.size()]));
    }

    return result;
  }
    public String getName() {

      if (name != null) return name;

      if (isGetter) {
        return name = String.format("%s()", getIdentifier());
      } else {
        String elemName = field.getElementName();
        String type = getType();
        String param = "";
        if (type != null && type != "") {
          param += type + " ";
        }
        param += elemName;
        return name = String.format("%s(%s)", getIdentifier(), param);
      }
    }
 @Deprecated
 protected final String processFieldName(IField field, String token) {
   return field.getElementName();
 }
  public IGoal[] init() {
    ClassVariableDeclarationGoal typedGoal = (ClassVariableDeclarationGoal) goal;
    IType[] types = typedGoal.getTypes();

    if (types == null) {
      TypeContext context = (TypeContext) typedGoal.getContext();
      types = PHPTypeInferenceUtils.getModelElements(context.getInstanceType(), context);
    }
    if (types == null) {
      return null;
    }

    IContext context = typedGoal.getContext();
    IModelAccessCache cache = null;
    if (context instanceof IModelCacheContext) {
      cache = ((IModelCacheContext) context).getCache();
    }

    String variableName = typedGoal.getVariableName();

    final List<IGoal> subGoals = new LinkedList<IGoal>();
    for (final IType type : types) {
      try {
        ITypeHierarchy hierarchy = null;
        if (cache != null) {
          hierarchy = cache.getSuperTypeHierarchy(type, null);
        }
        IField[] fields =
            PHPModelUtils.getTypeHierarchyField(type, hierarchy, variableName, true, null);
        Map<IType, IType> fieldDeclaringTypeSet = new HashMap<IType, IType>();
        for (IField field : fields) {
          IType declaringType = field.getDeclaringType();
          if (declaringType != null) {
            fieldDeclaringTypeSet.put(declaringType, type);
            ISourceModule sourceModule = declaringType.getSourceModule();
            ModuleDeclaration moduleDeclaration =
                SourceParserUtil.getModuleDeclaration(sourceModule);
            TypeDeclaration typeDeclaration =
                PHPModelUtils.getNodeByClass(moduleDeclaration, declaringType);

            if (typeDeclaration != null && field instanceof SourceRefElement) {
              SourceRefElement sourceRefElement = (SourceRefElement) field;
              ISourceRange sourceRange = sourceRefElement.getSourceRange();

              ClassDeclarationSearcher searcher =
                  new ClassDeclarationSearcher(
                      sourceModule,
                      typeDeclaration,
                      sourceRange.getOffset(),
                      sourceRange.getLength(),
                      null,
                      type,
                      declaringType);
              try {
                moduleDeclaration.traverse(searcher);
                if (searcher.getResult() != null) {
                  subGoals.add(new ExpressionTypeGoal(searcher.getContext(), searcher.getResult()));
                }
              } catch (Exception e) {
                if (DLTKCore.DEBUG) {
                  e.printStackTrace();
                }
              }
            }
          }
        }

        if (subGoals.size() == 0) {
          getGoalFromStaticDeclaration(variableName, subGoals, type, null);
        }
        fieldDeclaringTypeSet.remove(type);
        if (subGoals.size() == 0 && !fieldDeclaringTypeSet.isEmpty()) {
          for (Iterator iterator = fieldDeclaringTypeSet.keySet().iterator();
              iterator.hasNext(); ) {
            IType fieldDeclaringType = (IType) iterator.next();
            getGoalFromStaticDeclaration(
                variableName,
                subGoals,
                fieldDeclaringType,
                fieldDeclaringTypeSet.get(fieldDeclaringType));
          }
        }
      } catch (CoreException e) {
        if (DLTKCore.DEBUG) {
          e.printStackTrace();
        }
      }
    }

    resolveMagicClassVariableDeclaration(types, variableName, cache);

    return subGoals.toArray(new IGoal[subGoals.size()]);
  }
  public IGoal[] init() {
    PHPDocClassVariableGoal typedGoal = (PHPDocClassVariableGoal) goal;
    TypeContext context = (TypeContext) typedGoal.getContext();
    String variableName = typedGoal.getVariableName();
    int offset = typedGoal.getOffset();

    IModelAccessCache cache = context.getCache();
    IType[] types =
        PHPTypeInferenceUtils.getModelElements(context.getInstanceType(), context, offset, cache);
    Map<PHPDocBlock, IField> docs = new HashMap<PHPDocBlock, IField>();
    // remove array index from field name
    if (variableName.endsWith("]")) { // $NON-NLS-1$
      int index = variableName.indexOf("["); // $NON-NLS-1$
      if (index != -1) {
        variableName = variableName.substring(0, index);
      }
    }
    if (types != null) {
      for (IType type : types) {
        try {
          // we look in whole hiearchy
          ITypeHierarchy superHierarchy;
          if (cache != null) {
            superHierarchy = cache.getSuperTypeHierarchy(type, null);
          } else {
            superHierarchy = type.newSupertypeHierarchy(null);
          }
          IType[] superTypes = superHierarchy.getAllTypes();
          for (IType superType : superTypes) {
            IField[] typeField = PHPModelUtils.getTypeField(superType, variableName, true);
            if (typeField.length > 0) {
              PHPDocBlock docBlock = PHPModelUtils.getDocBlock(typeField[0]);
              if (docBlock != null) {
                docs.put(docBlock, typeField[0]);
              }
            }
          }
        } catch (ModelException e) {
          if (DLTKCore.DEBUG) {
            e.printStackTrace();
          }
        }
      }
    }

    for (Entry<PHPDocBlock, IField> entry : docs.entrySet()) {
      PHPDocBlock doc = entry.getKey();
      IField typeField = entry.getValue();
      IType currentNamespace = PHPModelUtils.getCurrentNamespace(typeField);

      IModelElement space =
          currentNamespace != null ? currentNamespace : typeField.getSourceModule();

      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(variableName)) {
          continue;
        }

        evaluated.addAll(
            Arrays.asList(
                PHPEvaluationUtils.evaluatePHPDocType(
                    tag.getTypeReferences(), space, tag.sourceStart(), null)));
      }
    }

    return IGoal.NO_GOALS;
  }
    public String getRawFieldName() {

      if (raw != null) return raw;

      return raw = field.getElementName().replace("$", "");
    }
  private void generate(
      final List<GetterSetterEntry> entries, final int modifier, final boolean generateComments)
      throws Exception {

    ISourceModule source = type.getSourceModule();
    String name = type.getElementName().replace("$", "");
    StringBuffer buffer = new StringBuffer(name);
    buffer.replace(0, 1, Character.toString(Character.toUpperCase(name.charAt(0))));
    name = buffer.toString();

    ASTParser parser = ASTParser.newParser(source);
    parser.setSource(document.get().toCharArray());

    Program program = parser.createAST(new NullProgressMonitor());
    //		program.recordModifications();
    //		AST ast = program.getAST();

    ISourceRange range = type.getSourceRange();
    ASTNode node = program.getElementAt(range.getOffset());

    if (!(node instanceof ClassDeclaration)) {
      return;
    }

    char indentChar = FormatPreferencesSupport.getInstance().getIndentationChar(document);
    String indent = String.valueOf(indentChar);

    ClassDeclaration clazz = (ClassDeclaration) node;
    Block body = clazz.getBody();
    List<Statement> bodyStatements = body.statements();

    int end = bodyStatements.get(bodyStatements.size() - 1).getEnd();

    if (insertFirst) {
      end = bodyStatements.get(0).getStart() - 1;
    } else if (insertAfter != null) {

      boolean found = false;

      for (IMethod method : type.getMethods()) {
        if (method == insertAfter) {
          ISourceRange r = method.getSourceRange();
          end = r.getOffset() + r.getLength();
          found = true;
        }
      }

      if (!found) {
        for (IField field : type.getFields()) {
          ISourceRange r = field.getSourceRange();
          end = r.getOffset() + r.getLength() + 1;
        }
      }
    }

    lineDelim = TextUtilities.getDefaultLineDelimiter(document);
    String methods = "";

    int i = 0;
    for (GetterSetterEntry entry : entries) {

      String code = "";

      if (!entry.isGetter) {
        code =
            GetterSetterUtil.getSetterStub(
                entry.field,
                entry.getIdentifier(),
                entry.getType(),
                generateComments,
                modifier,
                indent);

      } else {
        code =
            GetterSetterUtil.getGetterStub(
                entry.field, entry.getIdentifier(), generateComments, modifier, indent);
      }

      code = lineDelim + code;
      String formatted = indentPattern(code, indent, lineDelim);

      if (i++ == 0) {
        formatted = lineDelim + formatted;
      }

      methods += formatted;
    }

    document.replace(end, 0, methods);

    Formatter formatter = new Formatter();
    Region region = new Region(end, methods.length());
    formatter.format(document, region);
  }