qmljs: sync parser with current 5.12 state

Task-number: QTCREATORBUG-22474
Change-Id: I86d7ee7cc28e95f814f2ba36551a36c8a59e1a79
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Tim Jenssen
2019-06-19 19:42:15 +02:00
committed by Tim Jenssen
parent 3333f1b8ac
commit 44f1d18307
2 changed files with 48 additions and 22 deletions

View File

@@ -116,6 +116,7 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode)
_tokenText.reserve(1024); _tokenText.reserve(1024);
_errorMessage.clear(); _errorMessage.clear();
_tokenSpell = QStringRef(); _tokenSpell = QStringRef();
_rawString = QStringRef();
_codePtr = code.unicode(); _codePtr = code.unicode();
_endPtr = _codePtr + code.length(); _endPtr = _codePtr + code.length();
@@ -149,13 +150,20 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode)
void Lexer::scanChar() void Lexer::scanChar()
{ {
unsigned sequenceLength = isLineTerminatorSequence(); if (_skipLinefeed) {
Q_ASSERT(*_codePtr == QLatin1Char('\n'));
++_codePtr;
_skipLinefeed = false;
}
_char = *_codePtr++; _char = *_codePtr++;
if (sequenceLength == 2)
_char = *_codePtr++;
++_currentColumnNumber; ++_currentColumnNumber;
if (isLineTerminator()) { if (isLineTerminator()) {
if (_char == QLatin1Char('\r')) {
if (_codePtr < _endPtr && *_codePtr == QLatin1Char('\n'))
_skipLinefeed = true;
_char = QLatin1Char('\n');
}
++_currentLineNumber; ++_currentLineNumber;
_currentColumnNumber = 0; _currentColumnNumber = 0;
} }
@@ -232,6 +240,7 @@ int Lexer::lex()
again: again:
_tokenSpell = QStringRef(); _tokenSpell = QStringRef();
_rawString = QStringRef();
_tokenKind = scanToken(); _tokenKind = scanToken();
_tokenLength = _codePtr - _tokenStartPtr - 1; _tokenLength = _codePtr - _tokenStartPtr - 1;
@@ -807,12 +816,15 @@ int Lexer::scanString(ScanStringMode mode)
QChar quote = (mode == TemplateContinuation) ? QChar(TemplateHead) : QChar(mode); QChar quote = (mode == TemplateContinuation) ? QChar(TemplateHead) : QChar(mode);
bool multilineStringLiteral = false; bool multilineStringLiteral = false;
const QChar *startCode = _codePtr; const QChar *startCode = _codePtr - 1;
// in case we just parsed a \r, we need to reset this flag to get things working
// correctly in the loop below and afterwards
_skipLinefeed = false;
if (_engine) { if (_engine) {
while (_codePtr <= _endPtr) { while (_codePtr <= _endPtr) {
if (isLineTerminator() && quote != QLatin1Char('`')) { if (isLineTerminator()) {
if (qmlMode()) if ((quote == QLatin1Char('`') || qmlMode()))
break; break;
_errorCode = IllegalCharacter; _errorCode = IllegalCharacter;
_errorMessage = QCoreApplication::translate("QmlParser", "Stray newline in string literal"); _errorMessage = QCoreApplication::translate("QmlParser", "Stray newline in string literal");
@@ -822,7 +834,8 @@ int Lexer::scanString(ScanStringMode mode)
} else if (_char == '$' && quote == QLatin1Char('`')) { } else if (_char == '$' && quote == QLatin1Char('`')) {
break; break;
} else if (_char == quote) { } else if (_char == quote) {
_tokenSpell = _engine->midRef(startCode - _code.unicode() - 1, _codePtr - startCode); _tokenSpell = _engine->midRef(startCode - _code.unicode(), _codePtr - startCode - 1);
_rawString = _tokenSpell;
scanChar(); scanChar();
if (quote == QLatin1Char('`')) if (quote == QLatin1Char('`'))
@@ -835,28 +848,36 @@ int Lexer::scanString(ScanStringMode mode)
else else
return T_STRING_LITERAL; return T_STRING_LITERAL;
} }
scanChar(); // don't use scanChar() here, that would transform \r sequences and the midRef() call would create the wrong result
_char = *_codePtr++;
++_currentColumnNumber;
} }
} }
// rewind by one char, so things gets scanned correctly
--_codePtr;
_validTokenText = true; _validTokenText = true;
_tokenText.resize(0); _tokenText = QString(startCode, _codePtr - startCode);
startCode--;
while (startCode != _codePtr - 1) auto setRawString = [&](const QChar *end) {
_tokenText += *startCode++; QString raw(startCode, end - startCode - 1);
raw.replace(QLatin1String("\r\n"), QLatin1String("\n"));
raw.replace(QLatin1Char('\r'), QLatin1Char('\n'));
_rawString = _engine->newStringRef(raw);
};
scanChar();
while (_codePtr <= _endPtr) { while (_codePtr <= _endPtr) {
if (unsigned sequenceLength = isLineTerminatorSequence()) { if (_char == quote) {
multilineStringLiteral = true;
_tokenText += _char;
if (sequenceLength == 2)
_tokenText += *_codePtr;
scanChar();
} else if (_char == mode) {
scanChar(); scanChar();
if (_engine) if (_engine) {
_tokenSpell = _engine->newStringRef(_tokenText); _tokenSpell = _engine->newStringRef(_tokenText);
if (quote == QLatin1Char('`'))
setRawString(_codePtr - 1);
}
if (quote == QLatin1Char('`')) if (quote == QLatin1Char('`'))
_bracesCount = _outerTemplateBraceCount.pop(); _bracesCount = _outerTemplateBraceCount.pop();
@@ -871,8 +892,10 @@ int Lexer::scanString(ScanStringMode mode)
scanChar(); scanChar();
scanChar(); scanChar();
_bracesCount = 1; _bracesCount = 1;
if (_engine) if (_engine) {
_tokenSpell = _engine->newStringRef(_tokenText); _tokenSpell = _engine->newStringRef(_tokenText);
setRawString(_codePtr - 2);
}
return (mode == TemplateHead ? T_TEMPLATE_HEAD : T_TEMPLATE_MIDDLE); return (mode == TemplateHead ? T_TEMPLATE_HEAD : T_TEMPLATE_MIDDLE);
} else if (_char == QLatin1Char('\\')) { } else if (_char == QLatin1Char('\\')) {

View File

@@ -146,6 +146,7 @@ public:
int tokenStartColumn() const { return _tokenColumn; } int tokenStartColumn() const { return _tokenColumn; }
inline QStringRef tokenSpell() const { return _tokenSpell; } inline QStringRef tokenSpell() const { return _tokenSpell; }
inline QStringRef rawString() const { return _rawString; }
double tokenValue() const { return _tokenValue; } double tokenValue() const { return _tokenValue; }
QString tokenText() const; QString tokenText() const;
@@ -198,6 +199,7 @@ private:
QString _tokenText; QString _tokenText;
QString _errorMessage; QString _errorMessage;
QStringRef _tokenSpell; QStringRef _tokenSpell;
QStringRef _rawString;
const QChar *_codePtr; const QChar *_codePtr;
const QChar *_endPtr; const QChar *_endPtr;
@@ -233,6 +235,7 @@ private:
bool _followsClosingBrace; bool _followsClosingBrace;
bool _delimited; bool _delimited;
bool _qmlMode; bool _qmlMode;
bool _skipLinefeed = false;
int _generatorLevel = 0; int _generatorLevel = 0;
bool _staticIsKeyword = false; bool _staticIsKeyword = false;
}; };