Example #1
0
  private void getIndentFromState(
      List<IndentCommand> iis, boolean updateState, int lineStartOffset) {
    Stack<TplStackItem> blockStack = getStack();

    int lastUnprocessedItem = blockStack.size();
    for (int i = blockStack.size() - 1; i >= 0; i--) {
      if (!blockStack.get(i).processed) {
        lastUnprocessedItem = i;
      } else {
        break;
      }
    }
    for (int i = lastUnprocessedItem; i < blockStack.size(); i++) {
      TplStackItem item = blockStack.get(i);
      assert !item.processed : item;
      if (item.state == StackItemState.IN_BODY) {
        IndentCommand ii = new IndentCommand(IndentCommand.Type.INDENT, lineStartOffset);
        if (item.indent != -1) {
          ii.setFixedIndentSize(item.indent);
        }
        iis.add(ii);
        if (updateState) {
          item.processed = Boolean.TRUE;
        }
      } else if (item.state == StackItemState.BODY_FINISHED) {
        IndentCommand ii = new IndentCommand(IndentCommand.Type.RETURN, lineStartOffset);
        iis.add(ii);
        if (updateState) {
          item.processed = Boolean.TRUE;
          blockStack.remove(i);
          i--;
        }
      }
    }
  }
Example #2
0
  @Override
  protected List<IndentCommand> getLineIndent(
      IndenterContextData<TplTopTokenId> context, List<IndentCommand> preliminaryNextLineIndent)
      throws BadLocationException {
    Stack<TplStackItem> blockStack = getStack();
    List<IndentCommand> iis = new ArrayList<IndentCommand>();
    getIndentFromState(iis, true, context.getLineStartOffset());

    JoinedTokenSequence<TplTopTokenId> ts = context.getJoinedTokenSequences();
    ts.move(context.getLineStartOffset());

    boolean isSmartyBodyCommand = false;
    boolean isSmartyElseCommand = false;
    boolean afterDelimiter = false;
    int embeddingLevel = 0;
    String lastTplCommand = "";
    // iterate over tokens on the line and push to stack any changes
    while (!context.isBlankLine()
        && ts.moveNext()
        && ((ts.isCurrentTokenSequenceVirtual() && ts.offset() < context.getLineEndOffset())
            || ts.offset() <= context.getLineEndOffset())) {
      Token<TplTopTokenId> token = ts.token();
      if (token == null) {
        continue;
      } else if (ts.embedded() != null) {
        // indent for smarty command of the zero embedding level
        if (embeddingLevel == 1 && afterDelimiter) {
          if (token.id() == TplTopTokenId.T_SMARTY && context.isIndentThisLine()) {
            String tplToken = getFunctionalTplTokenId(token);
            isSmartyBodyCommand = isBodyCommand(tplToken, context);
            if (isSmartyBodyCommand) {
              lastTplCommand = tplToken;
              isSmartyElseCommand = isElseCommand(tplToken);
            }
          } else {
            isSmartyBodyCommand = false;
            isSmartyElseCommand = false;
          }
        }
        continue;
      }

      if (token.id() == TplTopTokenId.T_SMARTY_OPEN_DELIMITER) {
        afterDelimiter = true;
        embeddingLevel++;
        TplStackItem state = new TplStackItem(StackItemState.IN_RULE);
        blockStack.push(state);
      } else if (token.id() == TplTopTokenId.T_SMARTY_CLOSE_DELIMITER) {
        afterDelimiter = false;
        if (isInState(blockStack, StackItemState.IN_RULE)) {
          // check that IN_RULE is the last state
          TplStackItem item = blockStack.pop();
          embeddingLevel--;
          if (embeddingLevel == 0) {
            assert item.state == StackItemState.IN_RULE;
            if (isSmartyBodyCommand) {
              if (!blockStack.isEmpty()
                  && isInRelatedCommand(lastTplCommand, blockStack.peek().getCommand())) {
                if (isSmartyElseCommand) {
                  String command = blockStack.pop().command;
                  blockStack.push(new TplStackItem(StackItemState.IN_BODY, command));
                } else {
                  blockStack.pop();
                }
                iis.add(new IndentCommand(IndentCommand.Type.RETURN, preservedLineIndentation));
              } else {
                blockStack.push(new TplStackItem(StackItemState.IN_BODY, lastTplCommand));
              }
            }
          }
        }
      } else if (isCommentToken(token)) {
        int start = context.getLineStartOffset();
        if (start < ts.offset()) {
          start = ts.offset();
        }
        int commentEndOffset = ts.offset() + ts.token().text().toString().trim().length() - 1;
        int end = context.getLineEndOffset();
        if (end > commentEndOffset) {
          end = commentEndOffset;
        }
        if (start > end) {
          // do nothing
        } else if (start == ts.offset()) {
          if (end < commentEndOffset) {
            // if comment ends on next line put formatter to IN_COMMENT state
            int lineStart = Utilities.getRowStart(getDocument(), ts.offset());
            preservedLineIndentation = start - lineStart;
          }
        } else if (end == commentEndOffset) {
          String text = getDocument().getText(start, end - start + 1).trim();
          if (!text.startsWith("*/")) {
            // if line does not start with '*/' then treat it as unformattable
            IndentCommand ic =
                new IndentCommand(
                    IndentCommand.Type.PRESERVE_INDENTATION, context.getLineStartOffset());
            ic.setFixedIndentSize(preservedLineIndentation);
            iis.add(ic);
          }
          preservedLineIndentation = -1;
        } else {
          IndentCommand ic =
              new IndentCommand(
                  IndentCommand.Type.PRESERVE_INDENTATION, context.getLineStartOffset());
          ic.setFixedIndentSize(preservedLineIndentation);
          iis.add(ic);
        }
      }
    }
    if (context.isBlankLine() && iis.isEmpty()) {
      IndentCommand ic =
          new IndentCommand(IndentCommand.Type.PRESERVE_INDENTATION, context.getLineStartOffset());
      ic.setFixedIndentSize(preservedLineIndentation);
      iis.add(ic);
    }

    if (iis.isEmpty()) {
      iis.add(new IndentCommand(IndentCommand.Type.NO_CHANGE, context.getLineStartOffset()));
    }

    if (context.getNextLineStartOffset() != -1) {
      getIndentFromState(preliminaryNextLineIndent, false, context.getNextLineStartOffset());
      if (preliminaryNextLineIndent.isEmpty()) {
        preliminaryNextLineIndent.add(
            new IndentCommand(IndentCommand.Type.NO_CHANGE, context.getNextLineStartOffset()));
      }
    }

    return iis;
  }