Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-132064

qmlFormat IndentingLineWriter: Regex detection consumes state

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • 6.8
    • 6.8
    • QML: Tooling
    • None
    • All

    Description

      This code will confuse the IndentingLineWriter because the "/" starts the regular expression detection and swallows the closing parenthesis.

              context.lineTo(width / 2, height); 

      Following lines will be indented to the opening parenthesis.

       

      The detection of regex consumes the state, and we need to restore it on error:

      bool Lexer::scanRegExp(RegExpBodyPrefix prefix)
      {
          _tokenText.resize(0);
          _state.validTokenText = true;
          _state.patternFlags = 0;
      
          const auto oldState = state();
          const auto oldCodePtr = _codePtr;
          const auto oldColumnNumber = _currentColumnNumber;
          const auto oldLineNumber = _currentLineNumber;
          const auto oldSkipLineFeed = _skipLinefeed;
          const auto oldTokenText = _tokenText;
      
          if (prefix == EqualPrefix)
              _tokenText += u'=';
      
          while (true) {
              switch (_state.currentChar.unicode()) {
      
              case u'/':
                  scanChar();            // scan the flags
                  _state.patternFlags = 0;
                  while (isIdentLetter(_state.currentChar)) {
                      int flag = regExpFlagFromChar(_state.currentChar);
                      if (flag == 0 || _state.patternFlags & flag) {
                          _errorMessage = QCoreApplication::translate(
                                                  "QQmlParser", "Invalid regular expression flag '%0'")
                                                  .arg(QChar(_state.currentChar));
                          goto error;
                      }
                      _state.patternFlags |= flag;
                      scanChar();
                  }
                  _tokenLength = _codePtr - _tokenStartPtr - 1;
                  return true;
      
              case u'\\':
                  // regular expression backslash sequence
                  _tokenText += _state.currentChar;
                  scanChar();
      
                  if (_codePtr > _endPtr || isLineTerminator()) {
                      _errorMessage = QCoreApplication::translate(
                              "QQmlParser", "Unterminated regular expression backslash sequence");
                      goto error;
                  }
                  _tokenText += _state.currentChar;
                  scanChar();
                  break;
      
              case u'[':
                  // regular expression class
                  _tokenText += _state.currentChar;
                  scanChar();
      
                  while (_codePtr <= _endPtr && !isLineTerminator()) {
                      if (_state.currentChar == u']')
                          break;
                      else if (_state.currentChar == u'\\') {
                          // regular expression backslash sequence
                          _tokenText += _state.currentChar;
                          scanChar();
      
                          if (_codePtr > _endPtr || isLineTerminator()) {
                              _errorMessage = QCoreApplication::translate(
                                      "QQmlParser", "Unterminated regular expression backslash sequence");
                              goto error;
                          }
                          _tokenText += _state.currentChar;
                          scanChar();
                      } else {
                          _tokenText += _state.currentChar;
                          scanChar();
                      }
                  }
      
                  if (_state.currentChar != u']') {
                      _errorMessage = QCoreApplication::translate(
                              "QQmlParser", "Unterminated regular expression class");
                      goto error;
                  }
                  _tokenText += _state.currentChar;
                  scanChar(); // skip ]
                  break;
      
              default:
                  if (_codePtr > _endPtr || isLineTerminator()) {
                      _errorMessage = QCoreApplication::translate(
                              "QQmlParser", "Unterminated regular expression literal");
                      goto error;
                  } else {
                      _tokenText += _state.currentChar;
                      scanChar();
                  }
              } // switch
          } // while
      
          error:
          //restore the state 
          setState(oldState);
      
          _codePtr = oldCodePtr;
          _currentColumnNumber = oldColumnNumber;
          _currentLineNumber = oldLineNumber;
          _skipLinefeed = oldSkipLineFeed;
          _tokenText = oldTokenText;
      
          return false;
      }
       

      This code will not fix false detections of regular expressions like this:

              context.lineTo(width / 2, height); // comment 

      In this case " 2, height); " will be wrongly recognized as a regular expression, again swallowing the closing parenthesis so all subsequent code will be indented to the opening parenthesis, we have no solution for that.

       

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            qtqmlteam Qt Qml Team User
            ovidiu.tepescu Ovidiu Tepescu
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes