示例#1
0
  /** Handles the case where we found a '#' in the code. */
  private int handleComment(
      FormatStd std,
      char[] cs,
      FastStringBuffer buf,
      FastStringBuffer tempBuf,
      ParsingUtils parsingUtils,
      int i) {
    if (std.spacesBeforeComment != FormatStd.DONT_HANDLE_SPACES) {
      for (int j = i - 1; j >= 0; j--) {
        char cj = cs[j];
        if (cj == '\t' || cj == ' ') {
          continue;
        }
        // Ok, found a non-whitespace -- if it's not a new line, we're after some
        // code, in which case we have to put the configured amount of spaces.
        if (cj != '\r' && cj != '\n') {
          buf.rightTrim();
          buf.appendN(' ', std.spacesBeforeComment);
        }
        break;
      }
    }

    tempBuf.clear();
    i = parsingUtils.eatComments(tempBuf, i);
    if (std.trimLines) {
      String endLine = "";
      if (tempBuf.endsWith("\r\n")) {
        endLine = "\r\n";
        tempBuf.deleteLastChars(2);
      } else if (tempBuf.endsWith('\r') || tempBuf.endsWith('\n')) {
        endLine += tempBuf.lastChar();
        tempBuf.deleteLast();
      }
      tempBuf.rightTrim();
      tempBuf.append(endLine);
    }

    formatComment(std, tempBuf);

    buf.append(tempBuf);
    return i;
  }
示例#2
0
 /**
  * We just want to trim whitespaces, not newlines!
  *
  * @param locBuf the buffer to be trimmed
  * @return the same buffer passed as a parameter
  */
 private FastStringBuffer rtrim(FastStringBuffer locBuf) {
   while (locBuf.length() > 0 && (locBuf.lastChar() == ' ' || locBuf.lastChar() == '\t')) {
     locBuf.deleteLast();
   }
   return locBuf;
 }
示例#3
0
  /**
   * Handles having an operator
   *
   * @param std the coding standard to be used
   * @param cs the contents of the string
   * @param buf the buffer where the contents should be added
   * @param parsingUtils helper to get the contents
   * @param i current index
   * @param c current char
   * @return the new index after handling the operator
   */
  private int handleOperator(
      FormatStd std, char[] cs, FastStringBuffer buf, ParsingUtils parsingUtils, int i, char c) {
    // let's discover if it's an unary operator (~ + -)
    boolean isUnaryWithContents = true;

    boolean isUnary = false;
    boolean changeWhitespacesBefore = true;
    if (c == '~' || c == '+' || c == '-') {
      // could be an unary operator...
      String trimmedLastWord = buf.getLastWord().trim();
      isUnary =
          trimmedLastWord.length() == 0 || PySelection.ALL_KEYWORD_TOKENS.contains(trimmedLastWord);

      if (!isUnary) {
        for (char itChar : buf.reverseIterator()) {
          if (itChar == ' ' || itChar == '\t') {
            continue;
          }

          switch (itChar) {
            case '[':
            case '{':
            case '=':
              changeWhitespacesBefore = false;

            case '(':
            case ':':
              isUnaryWithContents = false;

            case '>':
            case '<':

            case '-':
            case '+':
            case '~':

            case '*':
            case '/':
            case '%':
            case '!':
            case '&':
            case '^':
            case '|':
            case ',':
              isUnary = true;
          }
          break;
        }
      } else {
        isUnaryWithContents = buf.length() > 0;
      }
    }

    if (!isUnary) {
      // We don't want to change whitespaces before in a binary operator that is in a new line.
      for (char ch : buf.reverseIterator()) {
        if (!Character.isWhitespace(ch)) {
          break;
        }
        if (ch == '\r' || ch == '\n') {
          changeWhitespacesBefore = false;
          break;
        }
      }
    }

    if (changeWhitespacesBefore) {
      while (buf.length() > 0 && (buf.lastChar() == ' ' || buf.lastChar() == ' ')) {
        buf.deleteLast();
      }
    }

    boolean surroundWithSpaces = std.operatorsWithSpace;

    if (changeWhitespacesBefore) {
      // add spaces before
      if (isUnaryWithContents && surroundWithSpaces) {
        buf.append(' ');
      }
    }

    char localC = c;
    char prev = '\0';
    boolean backOne = true;
    while (isOperatorPart(localC, prev)) {
      buf.append(localC);
      prev = localC;
      i++;
      if (i == cs.length) {
        break;
      }
      localC = cs[i];
      if (localC == '=') {
        // when we get to an assign, we have found a full stmt (with assign) -- e.g.: a \\=  a += a
        // ==
        buf.append(localC);
        backOne = false;
        break;
      }
    }
    if (backOne) {
      i--;
    }

    // add space after only if it's not unary
    if (!isUnary && surroundWithSpaces) {
      buf.append(' ');
    }

    i = parsingUtils.eatWhitespaces(null, i + 1);
    return i;
  }
示例#4
0
  /**
   * This method formats a string given some standard.
   *
   * @param str the string to be formatted
   * @param std the standard to be used
   * @param parensLevel the level of the parenthesis available.
   * @return a new (formatted) string
   * @throws SyntaxErrorException
   */
  private String formatStr(
      String str, FormatStd std, int parensLevel, String delimiter, boolean throwSyntaxError)
      throws SyntaxErrorException {
    char[] cs = str.toCharArray();
    FastStringBuffer buf = new FastStringBuffer();

    // Temporary buffer for some operations. Must always be cleared before it's used.
    FastStringBuffer tempBuf = new FastStringBuffer();

    ParsingUtils parsingUtils = ParsingUtils.create(cs, throwSyntaxError);
    char lastChar = '\0';
    for (int i = 0; i < cs.length; i++) {
      char c = cs[i];

      switch (c) {
        case '\'':
        case '"':
          // ignore literals and multi-line literals, including comments...
          i = parsingUtils.eatLiterals(buf, i, std.trimMultilineLiterals);
          break;

        case '#':
          i = handleComment(std, cs, buf, tempBuf, parsingUtils, i);
          break;

        case ',':
          i = formatForComma(std, cs, buf, i, tempBuf);
          break;

        case '(':
          i =
              formatForPar(
                  parsingUtils, cs, i, std, buf, parensLevel + 1, delimiter, throwSyntaxError);
          break;

          // Things to treat:
          // +, -, *, /, %
          // ** // << >>
          // <, >, !=, <>, <=, >=, //=, *=, /=,
          // & ^ ~ |
        case '*':
          // for *, we also need to treat when it's used in varargs, kwargs and list expansion
          boolean isOperator = false;
          for (int j = buf.length() - 1; j >= 0; j--) {
            char localC = buf.charAt(j);
            if (Character.isWhitespace(localC)) {
              continue;
            }
            if (localC == '(' || localC == ',') {
              // it's not an operator, but vararg. kwarg or list expansion
            }
            if (Character.isJavaIdentifierPart(localC)) {
              // ok, there's a chance that it can be an operator, but we still have to check
              // the chance that it's a wild import
              tempBuf.clear();
              while (Character.isJavaIdentifierPart(localC)) {
                tempBuf.append(localC);
                j--;
                if (j < 0) {
                  break; // break while
                }
                localC = buf.charAt(j);
              }
              String reversed = tempBuf.reverse().toString();
              if (!reversed.equals("import") && !reversed.equals("lambda")) {
                isOperator = true;
              }
            }
            if (localC == '\'' || localC == ')' || localC == ']') {
              isOperator = true;
            }

            // If it got here (i.e.: not whitespace), get out of the for loop.
            break;
          }
          if (!isOperator) {
            buf.append('*');
            break; // break switch
          }
          // Otherwise, FALLTHROUGH

        case '+':
        case '-':
          if (c == '-' || c == '+') { // could also be *

            // handle exponentials correctly: e.g.: 1e-6 cannot have a space
            tempBuf.clear();
            boolean started = false;

            for (int j = buf.length() - 1; ; j--) {
              if (j < 0) {
                break;
              }
              char localC = buf.charAt(j);
              if (localC == ' ' || localC == '\t') {
                if (!started) {
                  continue;
                } else {
                  break;
                }
              }
              started = true;
              if (Character.isJavaIdentifierPart(localC) || localC == '.') {
                tempBuf.append(localC);
              } else {
                break; // break for
              }
            }
            boolean isExponential = true;
            String partialNumber = tempBuf.reverse().toString();
            int partialLen = partialNumber.length();
            if (partialLen < 2 || !Character.isDigit(partialNumber.charAt(0))) {
              // at least 2 chars: the number and the 'e'
              isExponential = false;
            } else {
              // first char checked... now, if the last is an 'e', we must leave it together no
              // matter what
              if (partialNumber.charAt(partialLen - 1) != 'e'
                  && partialNumber.charAt(partialLen - 1) != 'E') {
                isExponential = false;
              }
            }
            if (isExponential) {
              buf.rightTrim();
              buf.append(c);
              // skip the next whitespaces from the buffer
              int initial = i;
              do {
                i++;
              } while (i < cs.length && (c = cs[i]) == ' ' || c == '\t');
              if (i > initial) {
                i--; // backup 1 because we walked 1 too much.
              }
              break; // break switch
            }
            // Otherwise, FALLTHROUGH
          }

        case '/':
        case '%':
        case '<':
        case '>':
        case '!':
        case '&':
        case '^':
        case '~':
        case '|':
          i = handleOperator(std, cs, buf, parsingUtils, i, c);
          c = cs[i];
          break;

          // check for = and == (other cases that have an = as the operator should already be
          // treated)
        case '=':
          if (i < cs.length - 1 && cs[i + 1] == '=') {
            // if == handle as if a regular operator
            i = handleOperator(std, cs, buf, parsingUtils, i, c);
            c = cs[i];
            break;
          }

          while (buf.length() > 0 && buf.lastChar() == ' ') {
            buf.deleteLast();
          }

          boolean surroundWithSpaces = std.operatorsWithSpace;
          if (parensLevel > 0) {
            surroundWithSpaces = std.assignWithSpaceInsideParens;
          }

          // add space before
          if (surroundWithSpaces) {
            buf.append(' ');
          }

          // add the operator and the '='
          buf.append('=');

          // add space after
          if (surroundWithSpaces) {
            buf.append(' ');
          }

          i = parsingUtils.eatWhitespaces(null, i + 1);
          break;

        default:
          if (c == '\r' || c == '\n') {
            if (lastChar == ',' && std.spaceAfterComma && buf.lastChar() == ' ') {
              buf.deleteLast();
            }
            if (std.trimLines) {
              buf.rightTrim();
            }
          }
          buf.append(c);
      }
      lastChar = c;
    }
    if (parensLevel == 0 && std.trimLines) {
      buf.rightTrim();
    }
    return buf.toString();
  }