diff --git a/src/libs/cplusplus/MatchingText.cpp b/src/libs/cplusplus/MatchingText.cpp index 0ae26f5b1229ee8369a1f5ddf7c3d3bf66683f81..0ee23ac4e8837b34110245c656aef49d1b93f80e 100644 --- a/src/libs/cplusplus/MatchingText.cpp +++ b/src/libs/cplusplus/MatchingText.cpp @@ -109,7 +109,7 @@ QString MatchingText::insertMatchingBrace(const QTextCursor &cursor, const QStri QTextDocument *doc = tc.document(); QString text = textToProcess; - const QString blockText = tc.block().text().mid(tc.columnNumber()); + const QString blockText = tc.block().text().mid(tc.positionInBlock()); const int length = qMin(blockText.length(), textToProcess.length()); const QChar previousChar = doc->characterAt(tc.selectionEnd() - 1); @@ -219,7 +219,7 @@ QString MatchingText::insertParagraphSeparator(const QTextCursor &tc) const if (tk[index - 1].isNot(T_LBRACE)) return QString(); // nothing to do. - const QString textBlock = tc.block().text().mid(tc.columnNumber()).trimmed(); + const QString textBlock = tc.block().text().mid(tc.positionInBlock()).trimmed(); if (! textBlock.isEmpty()) return QString(); diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index f68f3286d4141899a31e4d8064de7175a4abfcff..19c92b21a76e718d116fa1e5cdc2653e3bd702ed 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -1421,6 +1421,37 @@ bool CPPEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, return true; } +bool CPPEditor::contextAllowsElectricCharacters(const QTextCursor &cursor) const +{ + const SimpleToken tk = tokenCache()->tokenUnderCursor(cursor); + + // XXX Duplicated from CPPEditor::isInComment to avoid tokenizing twice + if (tk.isComment()) { + const int pos = cursor.selectionEnd() - cursor.block().position(); + + if (pos == tk.end()) { + if (tk.is(T_CPP_COMMENT) || tk.is(T_CPP_DOXY_COMMENT)) + return false; + + const int state = cursor.block().userState() & 0xFF; + if (state > 0) + return false; + } + + if (pos < tk.end()) + return false; + } + else if (tk.is(T_STRING_LITERAL) || tk.is(T_WIDE_STRING_LITERAL) + || tk.is(T_CHAR_LITERAL) || tk.is(T_WIDE_CHAR_LITERAL)) { + + const int pos = cursor.selectionEnd() - cursor.block().position(); + if (pos <= tk.end()) + return false; + } + + return true; +} + bool CPPEditor::isInComment(const QTextCursor &cursor) const { const SimpleToken tk = tokenCache()->tokenUnderCursor(cursor); @@ -1557,7 +1588,7 @@ void CPPEditor::contextMenuEvent(QContextMenuEvent *e) // ### enable // updateSemanticInfo(m_semanticHighlighter->semanticInfo(currentSource())); - QMenu *menu = new QMenu(); + QMenu *menu = new QMenu; Core::ActionManager *am = Core::ICore::instance()->actionManager(); Core::ActionContainer *mcontext = am->actionContainer(CppEditor::Constants::M_CONTEXT); diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 2ecba1e0760d07c7757408893cb5bc3caea98d2f..54dce843a5b905bcf97be3f11858f086e763557d 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -231,6 +231,7 @@ protected: virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert = QString()) const; + virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const; virtual bool isInComment(const QTextCursor &cursor) const; diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp index 7dd096a85b2e5268b252b95bc0242810faa5a800..9c8ed75979bfd0bfe1c6de22cd68b2d3e7a9d281 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -748,11 +748,11 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos, // Fetch the expression's code. CPlusPlus::ExpressionUnderCursor expressionUnderCursor(modelManager->tokenCache(editor)); expr = expressionUnderCursor(tc); - *column = tc.columnNumber(); + *column = tc.positionInBlock(); *line = tc.blockNumber(); } else { const QTextCursor tc = plaintext->textCursor(); - *column = tc.columnNumber(); + *column = tc.positionInBlock(); *line = tc.blockNumber(); } diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 8d039d9486eeb9e5f0563a3c060f1e12f9679642..27c7c48a649d4a8d421e6fbd9fd0fb44cb1bbef1 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -1464,8 +1464,8 @@ void FakeVimHandler::Private::updateSelection() } else if (isVisualBlockMode()) { QTextCursor tc = m_tc; tc.setPosition(anchorPos); - int anchorColumn = tc.columnNumber(); - int cursorColumn = m_tc.columnNumber(); + int anchorColumn = tc.positionInBlock(); + int cursorColumn = m_tc.positionInBlock(); int anchorRow = tc.blockNumber(); int cursorRow = m_tc.blockNumber(); int startColumn = qMin(anchorColumn, cursorColumn); diff --git a/src/plugins/qmlinspector/components/expressionquerywidget.cpp b/src/plugins/qmlinspector/components/expressionquerywidget.cpp index 4aa2f1b7c9b871070737a9268b86048aa6f36569..830ce28756404b5397653ae3de2855a366379a7e 100644 --- a/src/plugins/qmlinspector/components/expressionquerywidget.cpp +++ b/src/plugins/qmlinspector/components/expressionquerywidget.cpp @@ -283,7 +283,7 @@ bool ExpressionQueryWidget::eventFilter(QObject *obj, QEvent *event) bool atLastLine = !(cursor.block().next().isValid()); if (!atLastLine) return true; - if (cursor.columnNumber() <= m_prompt.count()) + if (cursor.positionInBlock() <= m_prompt.count()) return true; cursor.deletePreviousChar(); m_expr = cursor.block().text().mid(m_prompt.count()); diff --git a/src/plugins/qmljseditor/qmlexpressionundercursor.cpp b/src/plugins/qmljseditor/qmlexpressionundercursor.cpp index d5a82a5eccbf30d308e895a7714ebaad09286095..d6b2604eb4f3e73bf119436892b84704ba450785 100644 --- a/src/plugins/qmljseditor/qmlexpressionundercursor.cpp +++ b/src/plugins/qmljseditor/qmlexpressionundercursor.cpp @@ -102,7 +102,7 @@ public: _cursor = cursor; QTextBlock block = _cursor.block(); - const QString blockText = block.text().left(cursor.columnNumber()); + const QString blockText = block.text().left(cursor.positionInBlock()); scanner.setScanComments(false); const QList<Token> tokens = scanner(blockText, startState(block)); diff --git a/src/plugins/qmljseditor/qmljscodecompletion.cpp b/src/plugins/qmljseditor/qmljscodecompletion.cpp index c99696474478297ab83abcd11bcde027d010a25c..1c5e80fcabd71bd0d6b0a97e87c24c76e785d659 100644 --- a/src/plugins/qmljseditor/qmljscodecompletion.cpp +++ b/src/plugins/qmljseditor/qmljscodecompletion.cpp @@ -523,7 +523,7 @@ bool CodeCompletion::triggersCompletion(TextEditor::ITextEditable *editor) QTextCursor tc = ed->textCursor(); QTextBlock block = tc.block(); - const int column = tc.columnNumber(); + const int column = tc.positionInBlock(); const int blockState = qMax(0, block.previous().userState()) & 0xff; const QString blockText = block.text(); diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index c730c616406376a008ed00bbef426c985ccca9e5..e87b91b1992f03f5f16027ee04b9b6c293033a19 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -1103,6 +1103,34 @@ static bool isCompleteStringLiteral(const QStringRef &text) return false; } +static Token tokenUnderCursor(const QTextCursor &cursor) +{ + const QString blockText = cursor.block().text(); + const int blockState = blockStartState(cursor.block()); + + Scanner tokenize; + const QList<Token> tokens = tokenize(blockText, blockState); + const int pos = cursor.positionInBlock(); + + int tokenIndex = 0; + for (; tokenIndex < tokens.size(); ++tokenIndex) { + const Token &token = tokens.at(tokenIndex); + + if (token.is(Token::Comment) || token.is(Token::String)) { + if (pos > token.begin() && pos <= token.end()) + break; + } else { + if (pos >= token.begin() && pos < token.end()) + break; + } + } + + if (tokenIndex != tokens.size()) + return tokens.at(tokenIndex); + + return Token(); +} + bool QmlJSTextEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert) const { QChar ch; @@ -1132,56 +1160,45 @@ bool QmlJSTextEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, co return false; } // end of switch - const QString blockText = cursor.block().text(); - const int blockState = blockStartState(cursor.block()); + const Token token = tokenUnderCursor(cursor); + switch (token.kind) { + case Token::Comment: + return false; - Scanner tokenize; - const QList<Token> tokens = tokenize(blockText, blockState); - const int pos = cursor.columnNumber(); + case Token::String: { + const QString blockText = cursor.block().text(); + const QStringRef tokenText = blockText.midRef(token.offset, token.length); + const QChar quote = tokenText.at(0); - int tokenIndex = 0; - for (; tokenIndex < tokens.size(); ++tokenIndex) { - const Token &token = tokens.at(tokenIndex); - - if (pos >= token.begin()) { - if (pos < token.end()) - break; + if (ch != quote || isCompleteStringLiteral(tokenText)) + break; - else if (pos == token.end() && (token.is(Token::Comment) || - token.is(Token::String))) - break; - } + return false; } - if (tokenIndex != tokens.size()) { - const Token &token = tokens.at(tokenIndex); - - switch (token.kind) { - case Token::Comment: - return false; - - case Token::String: { - const QStringRef tokenText = blockText.midRef(token.offset, token.length); - const QChar quote = tokenText.at(0); - - if (ch != quote || isCompleteStringLiteral(tokenText)) - break; + default: + break; + } // end of switch - return false; - } + return true; +} - default: - break; - } // end of switch +bool QmlJSTextEditor::contextAllowsElectricCharacters(const QTextCursor &cursor) const +{ + Token token = tokenUnderCursor(cursor); + qDebug() << cursor.positionInBlock() << token.begin() << token.end(); + switch (token.kind) { + case Token::Comment: + case Token::String: + return false; + default: + return true; } - - return true; } -bool QmlJSTextEditor::isInComment(const QTextCursor &) const +bool QmlJSTextEditor::isInComment(const QTextCursor &cursor) const { - // ### implement me - return false; + return tokenUnderCursor(cursor).is(Token::Comment); } QString QmlJSTextEditor::insertMatchingBrace(const QTextCursor &tc, const QString &text, QChar, int *skippedChars) const diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index 486170c40d78388982b9b76a8fbfd58f068c5228..22b06ddcc891dd299eedd75623751a2ad70ba3d1 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -248,6 +248,7 @@ protected: //// brace matching virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert = QString()) const; + virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const; virtual bool isInComment(const QTextCursor &cursor) const; virtual QString insertMatchingBrace(const QTextCursor &tc, const QString &text, QChar la, int *skippedChars) const; virtual QString insertParagraphSeparator(const QTextCursor &tc) const; diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 2612647ab4c038981625a2326b65a8b1477a064c..249666b2ac710056fd0d5f03db35abf64a52e1a8 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -1351,7 +1351,7 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e) cursor.insertText(autoText); cursor.setPosition(pos); } - if (!electricChar.isNull()) + if (!electricChar.isNull() && contextAllowsElectricCharacters(cursor)) indent(document(), cursor, electricChar); if (doEditBlock) @@ -3824,6 +3824,11 @@ bool BaseTextEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, return false; } +bool BaseTextEditor::contextAllowsElectricCharacters(const QTextCursor &cursor) const +{ + return contextAllowsAutoParentheses(cursor); +} + bool BaseTextEditor::isInComment(const QTextCursor &cursor) const { Q_UNUSED(cursor); diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h index 79058bd38903b0981717518ef2c5009585231130..e375375dec1f8ae1550bc14a9dc65684057340ef 100644 --- a/src/plugins/texteditor/basetexteditor.h +++ b/src/plugins/texteditor/basetexteditor.h @@ -407,6 +407,7 @@ public: virtual void reindent(QTextDocument *doc, const QTextCursor &cursor); virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert = QString()) const; + virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const; // Returns true if the cursor is inside a comment. virtual bool isInComment(const QTextCursor &cursor) const; diff --git a/src/plugins/texteditor/tabsettings.cpp b/src/plugins/texteditor/tabsettings.cpp index 20e80446634bf934333d798595fc1b20bc24acd1..9c7864a9cbd86b828663e881d76eb643f80a29d5 100644 --- a/src/plugins/texteditor/tabsettings.cpp +++ b/src/plugins/texteditor/tabsettings.cpp @@ -192,7 +192,7 @@ bool TabSettings::tabShouldIndent(const QTextDocument *document, QTextCursor cur return true; if (document->characterAt(tc.position()).isSpace()) { tc.movePosition(QTextCursor::WordRight); - if (tc.columnNumber() >= cursor.columnNumber()) { + if (tc.positionInBlock() >= cursor.positionInBlock()) { if (suggestedPosition) *suggestedPosition = tc.position(); // Suggest position after whitespace if (m_tabKeyBehavior == TabLeadingWhitespaceIndents)