@Override
  protected GocodeServerInstance doCreateServerInstance(IOperationMonitor om)
      throws CommonException, OperationCancellation {
    Path gocodePath = getServerPath();

    ArrayList2<String> commandLine = new ArrayList2<String>();
    commandLine.add(gocodePath.toString());
    commandLine.add("-s");
    if (GocodeCompletionOperation.USE_TCP) {
      commandLine.add("-sock=tcp");
    }

    LangCore.logInfo(
        "Starting gocode server: "
            + DebugPlugin.renderArguments(commandLine.toArray(String.class), null));

    ProcessBuilder pb = new ProcessBuilder(commandLine);

    IToolOperationMonitor opMonitor =
        toolMgr.startNewOperation(ProcessStartKind.ENGINE_SERVER, true, false);
    String prefixText = "==== Starting gocode server ====\n";

    gocodeSetEnableBuiltins(gocodePath, om, opMonitor, prefixText);

    ExternalProcessNotifyingHelper process =
        toolMgr.new RunToolTask(opMonitor, prefixText, null, pb, om).startProcess();

    return new GocodeServerInstance(gocodePath, process);
  }
  /**
   * * Add some partition rules common to C-style languages. All rules are optional, if an id is
   * null, the rule will not be added.
   */
  protected static void addStandardRules(
      ArrayList2<IPredicateRule> rules,
      String lineCommentId,
      String blockCommentId,
      String docLineCommentId,
      String docBlockCommentId,
      String stringId) {
    if (docLineCommentId != null) {
      rules.add(
          new PatternRule("///", null, new Token(docLineCommentId), NO_ESCAPE_CHAR, true, true));
    }
    if (docBlockCommentId != null) {
      rules.add(
          new PatternRule("/**", "*/", new Token(docBlockCommentId), NO_ESCAPE_CHAR, false, true));
    }

    if (lineCommentId != null) {
      rules.add(new PatternRule("//", null, new Token(lineCommentId), NO_ESCAPE_CHAR, true, true));
    }
    if (blockCommentId != null) {
      rules.add(
          new PatternRule("/*", "*/", new Token(blockCommentId), NO_ESCAPE_CHAR, false, true));
    }

    if (stringId != null) {
      rules.add(new PatternRule("\"", "\"", new Token(stringId), '\\', false, true));
    }
  }
  @Override
  public Indexable<IContextInformation> computeContextInformation(SourceOperationContext context) {
    clearErrorMessage();

    ArrayList2<IContextInformation> proposals = new ArrayList2<>();

    for (ILangCompletionProposalComputer computer : computers) {
      Indexable<IContextInformation> computerProposals =
          computer.computeContextInformation(context);
      if (computerProposals != null) {
        proposals.addAll2(computerProposals);
      }

      updateErrorMessage(computer.getErrorMessage());
    }
    return proposals;
  }
  @Override
  protected void initPredicateRules(ArrayList2<IPredicateRule> rules) {
    addStandardRules(
        rules,
        LangPartitionTypes.LINE_COMMENT.getId(),
        LangPartitionTypes.BLOCK_COMMENT.getId(),
        LangPartitionTypes.DOC_LINE_COMMENT.getId(),
        LangPartitionTypes.DOC_BLOCK_COMMENT.getId(),
        LangPartitionTypes.STRING.getId());

    rules.add(
        new PredicateRule_Adapter(LangPartitionTypes.CHARACTER.getId(), new CharacterLexingRule()));
  }