diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 1b4e59c82c0470e6e939402cad3eb21ee0dda00b..4db9047e77f97c5dc1299802414a4045a31e9c74 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -1588,6 +1588,38 @@ bool CPPEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, return true; } +bool CPPEditor::contextAllowsElectricCharacters(const QTextCursor &cursor) const +{ + CPlusPlus::TokenUnderCursor tokenUnderCursor; + const SimpleToken tk = 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 { CPlusPlus::TokenUnderCursor tokenUnderCursor; @@ -1729,7 +1761,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 35ba10f759d67cf55212f11b2eae331726ca5dbb..fb5758c58405b47cef7bad519c5e250229d1c9df 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -221,6 +221,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/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index b06e4791a27e5e82f4eb017c458dbf8fc240c502..d56368a042aa3041aca4f72e012ce1d9a7082709 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -1096,6 +1096,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; @@ -1125,56 +1153,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.positionInBlock(); + 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 cb1edfcf28dd364f60c9a8be4f751a55679eda57..5d24fdd3835868cac1a51365f8a80986d0fd4794 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -245,6 +245,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 90858bb4d5949b6db9a5a14325958ed6da8f022f..601e64555cb7bd9ea6acac184b571ce8f35dad53 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -1332,7 +1332,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) @@ -3856,6 +3856,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 066ec0d8a084325d01d470d31d490c0bf33ff48b..14d52b466ca2f93f6b42686d9f411faafea3f11c 100644 --- a/src/plugins/texteditor/basetexteditor.h +++ b/src/plugins/texteditor/basetexteditor.h @@ -403,6 +403,7 @@ protected: 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;