@Override
  public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {

    IDocument document = viewer.getDocument();
    ITextEditor textEditor = ((PHPStructuredTextViewer) viewer).getTextEditor();

    if (textEditor instanceof PHPStructuredEditor) {
      IModelElement editorElement = ((PHPStructuredEditor) textEditor).getModelElement();
      if (editorElement != null) {

        ISourceModule sourceModule = ((ModelElement) editorElement).getSourceModule();

        try {

          if (sourceModule.getTypes().length != 1) {
            return;
          }
          ModuleDeclaration module = SourceParserUtil.getModuleDeclaration(sourceModule);
          ImplementationValidator validator = new ImplementationValidator(sourceModule);
          String code = "";
          try {
            module.traverse(validator);
          } catch (Exception e) {
            e.getClass();
            e.printStackTrace();
          }
          char indentChar = FormatPreferencesSupport.getInstance().getIndentationChar(document);
          String indent = String.valueOf(indentChar);

          for (MissingMethodImplementation miss : validator.getMissing()) {

            for (IMethod method : miss.getMisses()) {
              code +=
                  MethodStub.getMethodStub(
                      method.getParent().getElementName(),
                      method,
                      method,
                      indent,
                      TextUtilities.getDefaultLineDelimiter(document),
                      true);
            }

            document.replace(miss.getInjectionOffset(), 0, code);

            UseStatementInjector injector = new UseStatementInjector(this);
            injector.inject(document, getTextViewer(), offset);

            // TODO: format code using new PDT formatter
            /*
            Formatter formatter = new Formatter();
            formatter.format(document);
            */

          }

        } catch (Exception e) {
          Logger.logException(e);
        }
      }
    }
  }
  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);
  }