From d34654c1aa9c1d42e1ed6332d050048ebb1e6489 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Mon, 26 May 2014 12:24:23 -0400 Subject: [PATCH] CppEditor: Extract CppDocumentationCommentHelper Change-Id: Iefaff837565f0aaf7e52263daa40a58fc391df36 Reviewed-by: Erik Verbruggen --- .../cppdocumentationcommenthelper.cpp | 323 ++++++++++++++++++ .../cppeditor/cppdocumentationcommenthelper.h | 66 ++++ src/plugins/cppeditor/cppeditor.cpp | 287 +--------------- src/plugins/cppeditor/cppeditor.h | 10 +- src/plugins/cppeditor/cppeditor.pro | 2 + src/plugins/cppeditor/cppeditor.qbs | 1 + 6 files changed, 401 insertions(+), 288 deletions(-) create mode 100644 src/plugins/cppeditor/cppdocumentationcommenthelper.cpp create mode 100644 src/plugins/cppeditor/cppdocumentationcommenthelper.h diff --git a/src/plugins/cppeditor/cppdocumentationcommenthelper.cpp b/src/plugins/cppeditor/cppdocumentationcommenthelper.cpp new file mode 100644 index 00000000000..2bd2e2bcec9 --- /dev/null +++ b/src/plugins/cppeditor/cppdocumentationcommenthelper.cpp @@ -0,0 +1,323 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "cppdocumentationcommenthelper.h" + +#include "cppautocompleter.h" + +#include +#include +#include + +#include +#include +#include + +using namespace CppTools; + +namespace { + +bool isStartOfDoxygenComment(const QTextCursor &cursor) +{ + const int pos = cursor.position(); + + QTextDocument *document = cursor.document(); + QString comment = QString(document->characterAt(pos - 3)) + + document->characterAt(pos - 2) + + document->characterAt(pos - 1); + + if ((comment == QLatin1String("/**")) + || (comment == QLatin1String("/*!")) + || (comment == QLatin1String("///")) + || (comment == QLatin1String("//!"))) { + return true; + } + return false; +} + +DoxygenGenerator::DocumentationStyle doxygenStyle(const QTextCursor &cursor, + const QTextDocument *doc) +{ + const int pos = cursor.position(); + + QString comment = QString(doc->characterAt(pos - 3)) + + doc->characterAt(pos - 2) + + doc->characterAt(pos - 1); + + if (comment == QLatin1String("/**")) + return DoxygenGenerator::JavaStyle; + else if (comment == QLatin1String("/*!")) + return DoxygenGenerator::QtStyle; + else if (comment == QLatin1String("///")) + return DoxygenGenerator::CppStyleA; + else + return DoxygenGenerator::CppStyleB; +} + +/// Check if previous line is a CppStyle Doxygen Comment +bool isPreviousLineCppStyleComment(const QTextCursor &cursor) +{ + const QTextBlock ¤tBlock = cursor.block(); + if (!currentBlock.isValid()) + return false; + + const QTextBlock &actual = currentBlock.previous(); + if (!actual.isValid()) + return false; + + const QString text = actual.text().trimmed(); + if (text.startsWith(QLatin1String("///")) || text.startsWith(QLatin1String("//!"))) + return true; + + return false; +} + +/// Check if next line is a CppStyle Doxygen Comment +bool isNextLineCppStyleComment(const QTextCursor &cursor) +{ + const QTextBlock ¤tBlock = cursor.block(); + if (!currentBlock.isValid()) + return false; + + const QTextBlock &actual = currentBlock.next(); + if (!actual.isValid()) + return false; + + const QString text = actual.text().trimmed(); + if (text.startsWith(QLatin1String("///")) || text.startsWith(QLatin1String("//!"))) + return true; + + return false; +} + +bool isCppStyleContinuation(const QTextCursor& cursor) +{ + return (isPreviousLineCppStyleComment(cursor) || isNextLineCppStyleComment(cursor)); +} + +/// Check if line is a CppStyle Doxygen comment and the cursor is after the comment +bool isCursorAfterCppComment(const QTextCursor &cursor, const QTextDocument *doc) +{ + QTextCursor cursorFirstNonBlank(cursor); + cursorFirstNonBlank.movePosition(QTextCursor::StartOfLine); + while (doc->characterAt(cursorFirstNonBlank.position()).isSpace() + && cursorFirstNonBlank.movePosition(QTextCursor::NextCharacter)) { + } + + const QTextBlock& block = cursorFirstNonBlank.block(); + const QString text = block.text().trimmed(); + if (text.startsWith(QLatin1String("///")) || text.startsWith(QLatin1String("//!"))) + return (cursor.position() >= cursorFirstNonBlank.position() + 3); + + return false; +} + +bool handleDoxygenCppStyleContinuation(QTextCursor &cursor, QKeyEvent *e) +{ + const int blockPos = cursor.positionInBlock(); + const QString &text = cursor.block().text(); + int offset = 0; + for (; offset < blockPos; ++offset) { + if (!text.at(offset).isSpace()) + break; + } + + // If the line does not start with the comment we don't + // consider it as a continuation. Handles situations like: + // void d(); /// + if (!(text.trimmed().startsWith(QLatin1String("///")) + || text.startsWith(QLatin1String("//!")))) { + return false; + } + + QString newLine(QLatin1Char('\n')); + newLine.append(QString(offset, QLatin1Char(' '))); // indent correctly + + const QString commentMarker = text.mid(offset, 3); + newLine.append(commentMarker); + newLine.append(QLatin1Char(' ')); + + cursor.insertText(newLine); + e->accept(); + return true; +} + +bool handleDoxygenContinuation(QTextCursor &cursor, + QKeyEvent *e, + const QTextDocument *doc, + const bool enableDoxygen, + const bool leadingAsterisks) +{ + // It might be a continuation if: + // a) current line starts with /// or //! and cursor is positioned after the comment + // b) current line is in the middle of a multi-line Qt or Java style comment + + if (enableDoxygen && !cursor.atEnd() && isCursorAfterCppComment(cursor, doc)) + return handleDoxygenCppStyleContinuation(cursor, e); + + if (!leadingAsterisks) + return false; + + // We continue the comment if the cursor is after a comment's line asterisk and if + // there's no asterisk immediately after the cursor (that would already be considered + // a leading asterisk). + int offset = 0; + const int blockPos = cursor.positionInBlock(); + const QString &text = cursor.block().text(); + for (; offset < blockPos; ++offset) { + if (!text.at(offset).isSpace()) + break; + } + + if (offset < blockPos + && (text.at(offset) == QLatin1Char('*') + || (offset < blockPos - 1 + && text.at(offset) == QLatin1Char('/') + && text.at(offset + 1) == QLatin1Char('*')))) { + int followinPos = blockPos; + for (; followinPos < text.length(); ++followinPos) { + if (!text.at(followinPos).isSpace()) + break; + } + if (followinPos == text.length() + || text.at(followinPos) != QLatin1Char('*')) { + QString newLine(QLatin1Char('\n')); + QTextCursor c(cursor); + c.movePosition(QTextCursor::StartOfBlock); + c.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, offset); + newLine.append(c.selectedText()); + if (text.at(offset) == QLatin1Char('/')) { + newLine.append(QLatin1String(" * ")); + } else { + int start = offset; + while (offset < blockPos && text.at(offset) == QLatin1Char('*')) + ++offset; + newLine.append(QString(offset - start, QLatin1Char('*'))); + newLine.append(QLatin1Char(' ')); + } + cursor.insertText(newLine); + e->accept(); + return true; + } + } + + return false; +} + +} // anonymous namespace + +namespace CppEditor { +namespace Internal { + +CppDocumentationCommentHelper::CppDocumentationCommentHelper( + TextEditor::BaseTextEditorWidget *editorWidget) + : m_editorWidget(editorWidget) + , m_settings(CppToolsSettings::instance()->commentsSettings()) +{ + connect(CppToolsSettings::instance(), + SIGNAL(commentsSettingsChanged(CppTools::CommentsSettings)), + this, + SLOT(onCommentsSettingsChanged(CppTools::CommentsSettings))); +} + +bool CppDocumentationCommentHelper::handleKeyPressEvent(QKeyEvent *e) const +{ + if (!m_settings.m_enableDoxygen && !m_settings.m_leadingAsterisks) + return false; + + if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { + QTextCursor cursor = m_editorWidget->textCursor(); + if (!m_editorWidget->autoCompleter()->isInComment(cursor)) + return false; + + // We are interested on two particular cases: + // 1) The cursor is right after a /**, /*!, /// or ///! and the user pressed enter. + // If Doxygen is enabled we need to generate an entire comment block. + // 2) The cursor is already in the middle of a multi-line comment and the user pressed + // enter. If leading asterisk(s) is set we need to write a comment continuation + // with those. + + if (m_settings.m_enableDoxygen && cursor.positionInBlock() >= 3) { + const int pos = cursor.position(); + if (isStartOfDoxygenComment(cursor)) { + QTextDocument *textDocument = m_editorWidget->document(); + DoxygenGenerator::DocumentationStyle style = doxygenStyle(cursor, textDocument); + + // Check if we're already in a CppStyle Doxygen comment => continuation + // Needs special handling since CppStyle does not have start and end markers + if ((style == DoxygenGenerator::CppStyleA || style == DoxygenGenerator::CppStyleB) + && isCppStyleContinuation(cursor)) { + return handleDoxygenCppStyleContinuation(cursor, e); + } + + DoxygenGenerator doxygen; + doxygen.setStyle(style); + doxygen.setAddLeadingAsterisks(m_settings.m_leadingAsterisks); + doxygen.setGenerateBrief(m_settings.m_generateBrief); + doxygen.setStartComment(false); + + // Move until we reach any possibly meaningful content. + while (textDocument->characterAt(cursor.position()).isSpace() + && cursor.movePosition(QTextCursor::NextCharacter)) { + } + + if (!cursor.atEnd()) { + const QString &comment = doxygen.generate(cursor); + if (!comment.isEmpty()) { + cursor.beginEditBlock(); + cursor.setPosition(pos); + cursor.insertText(comment); + cursor.setPosition(pos - 3, QTextCursor::KeepAnchor); + m_editorWidget->baseTextDocument()->autoIndent(cursor); + cursor.endEditBlock(); + e->accept(); + return true; + } + } + + } + } // right after first doxygen comment + + return handleDoxygenContinuation(cursor, + e, + m_editorWidget->document(), + m_settings.m_enableDoxygen, + m_settings.m_leadingAsterisks); + } + + return false; +} + +void CppDocumentationCommentHelper::onCommentsSettingsChanged(const CommentsSettings &settings) +{ + m_settings = settings; +} + +} // namespace Internal +} // namespace CppEditor diff --git a/src/plugins/cppeditor/cppdocumentationcommenthelper.h b/src/plugins/cppeditor/cppdocumentationcommenthelper.h new file mode 100644 index 00000000000..c8b81a3e03f --- /dev/null +++ b/src/plugins/cppeditor/cppdocumentationcommenthelper.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CPPDOCUMENTATIONCOMMENTHELPER_H +#define CPPDOCUMENTATIONCOMMENTHELPER_H + +#include + +#include + +QT_FORWARD_DECLARE_CLASS(QKeyEvent) + +namespace TextEditor { class BaseTextEditorWidget; } + +namespace CppEditor { +namespace Internal { + +class CppDocumentationCommentHelper : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(CppDocumentationCommentHelper) + +public: + explicit CppDocumentationCommentHelper(TextEditor::BaseTextEditorWidget *editorWidget); + bool handleKeyPressEvent(QKeyEvent *e) const; + +private slots: + void onCommentsSettingsChanged(const CppTools::CommentsSettings &settings); + +private: + CppDocumentationCommentHelper(); + + TextEditor::BaseTextEditorWidget *m_editorWidget; + CppTools::CommentsSettings m_settings; +}; + +} // namespace Internal +} // namespace CppEditor + +#endif // CPPDOCUMENTATIONCOMMENTHELPER_H diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 26e0eb8f0f1..f8ba5b0c407 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -33,6 +33,7 @@ #include "cppeditorconstants.h" #include "cppeditoroutline.h" #include "cppeditorplugin.h" +#include "cppdocumentationcommenthelper.h" #include "cppfollowsymbolundercursor.h" #include "cpphighlighter.h" #include "cpplocalrenaming.h" @@ -42,7 +43,6 @@ #include #include -#include #include #include #include @@ -53,8 +53,6 @@ #include #include #include -#include -#include #include #include @@ -201,176 +199,6 @@ public: }; -/// Check if previous line is a CppStyle Doxygen Comment -bool isPreviousLineCppStyleComment(const QTextCursor &cursor) -{ - const QTextBlock ¤tBlock = cursor.block(); - if (!currentBlock.isValid()) - return false; - - const QTextBlock &actual = currentBlock.previous(); - if (!actual.isValid()) - return false; - - const QString text = actual.text().trimmed(); - if (text.startsWith(QLatin1String("///")) || text.startsWith(QLatin1String("//!"))) - return true; - - return false; -} - -/// Check if next line is a CppStyle Doxygen Comment -bool isNextLineCppStyleComment(const QTextCursor &cursor) -{ - const QTextBlock ¤tBlock = cursor.block(); - if (!currentBlock.isValid()) - return false; - - const QTextBlock &actual = currentBlock.next(); - if (!actual.isValid()) - return false; - - const QString text = actual.text().trimmed(); - if (text.startsWith(QLatin1String("///")) || text.startsWith(QLatin1String("//!"))) - return true; - - return false; -} - -/// Check if line is a CppStyle Doxygen comment and the cursor is after the comment -bool isCursorAfterCppComment(const QTextCursor &cursor, const QTextDocument *doc) -{ - QTextCursor cursorFirstNonBlank(cursor); - cursorFirstNonBlank.movePosition(QTextCursor::StartOfLine); - while (doc->characterAt(cursorFirstNonBlank.position()).isSpace() - && cursorFirstNonBlank.movePosition(QTextCursor::NextCharacter)) { - } - - const QTextBlock& block = cursorFirstNonBlank.block(); - const QString text = block.text().trimmed(); - if (text.startsWith(QLatin1String("///")) || text.startsWith(QLatin1String("//!"))) - return (cursor.position() >= cursorFirstNonBlank.position() + 3); - - return false; -} - -bool isCppStyleContinuation(const QTextCursor& cursor) -{ - return (isPreviousLineCppStyleComment(cursor) || isNextLineCppStyleComment(cursor)); -} - -DoxygenGenerator::DocumentationStyle doxygenStyle(const QTextCursor &cursor, - const QTextDocument *doc) -{ - const int pos = cursor.position(); - - QString comment = QString(doc->characterAt(pos - 3)) - + doc->characterAt(pos - 2) - + doc->characterAt(pos - 1); - - if (comment == QLatin1String("/**")) - return CppTools::DoxygenGenerator::JavaStyle; - else if (comment == QLatin1String("/*!")) - return CppTools::DoxygenGenerator::QtStyle; - else if (comment == QLatin1String("///")) - return CppTools::DoxygenGenerator::CppStyleA; - else - return CppTools::DoxygenGenerator::CppStyleB; -} - -bool handleDoxygenCppStyleContinuation(QTextCursor &cursor, - QKeyEvent *e) -{ - const int blockPos = cursor.positionInBlock(); - const QString &text = cursor.block().text(); - int offset = 0; - for (; offset < blockPos; ++offset) { - if (!text.at(offset).isSpace()) - break; - } - - // If the line does not start with the comment we don't - // consider it as a continuation. Handles situations like: - // void d(); /// - if (!(text.trimmed().startsWith(QLatin1String("///")) - || text.startsWith(QLatin1String("//!")))) { - return false; - } - - QString newLine(QLatin1Char('\n')); - newLine.append(QString(offset, QLatin1Char(' '))); // indent correctly - - const QString commentMarker = text.mid(offset, 3); - newLine.append(commentMarker); - newLine.append(QLatin1Char(' ')); - - cursor.insertText(newLine); - e->accept(); - return true; -} - -bool handleDoxygenContinuation(QTextCursor &cursor, - QKeyEvent *e, - const QTextDocument *doc, - const bool enableDoxygen, - const bool leadingAsterisks) -{ - // It might be a continuation if: - // a) current line starts with /// or //! and cursor is positioned after the comment - // b) current line is in the middle of a multi-line Qt or Java style comment - - if (enableDoxygen && !cursor.atEnd() && isCursorAfterCppComment(cursor, doc)) - return handleDoxygenCppStyleContinuation(cursor, e); - - if (!leadingAsterisks) - return false; - - // We continue the comment if the cursor is after a comment's line asterisk and if - // there's no asterisk immediately after the cursor (that would already be considered - // a leading asterisk). - int offset = 0; - const int blockPos = cursor.positionInBlock(); - const QString &text = cursor.block().text(); - for (; offset < blockPos; ++offset) { - if (!text.at(offset).isSpace()) - break; - } - - if (offset < blockPos - && (text.at(offset) == QLatin1Char('*') - || (offset < blockPos - 1 - && text.at(offset) == QLatin1Char('/') - && text.at(offset + 1) == QLatin1Char('*')))) { - int followinPos = blockPos; - for (; followinPos < text.length(); ++followinPos) { - if (!text.at(followinPos).isSpace()) - break; - } - if (followinPos == text.length() - || text.at(followinPos) != QLatin1Char('*')) { - QString newLine(QLatin1Char('\n')); - QTextCursor c(cursor); - c.movePosition(QTextCursor::StartOfBlock); - c.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, offset); - newLine.append(c.selectedText()); - if (text.at(offset) == QLatin1Char('/')) { - newLine.append(QLatin1String(" * ")); - } else { - int start = offset; - while (offset < blockPos && text.at(offset) == QLatin1Char('*')) - ++offset; - newLine.append(QString(offset - start, QLatin1Char('*'))); - newLine.append(QLatin1Char(' ')); - } - cursor.insertText(newLine); - e->accept(); - return true; - } - } - - return false; -} - QTimer *newSingleShotTimer(QObject *parent, int msecInterval) { QTimer *timer = new QTimer(parent); @@ -408,6 +236,8 @@ public: CPPEditorDocument *m_cppEditorDocument; CppEditorOutline *m_cppEditorOutline; + CppDocumentationCommentHelper m_cppDocumentationCommentHelper; + QTimer *m_updateUsesTimer; QTimer *m_updateFunctionDeclDefLinkTimer; QHash m_semanticHighlightFormatMap; @@ -427,8 +257,6 @@ public: FunctionDeclDefLinkFinder *m_declDefLinkFinder; QSharedPointer m_declDefLink; - CppTools::CommentsSettings m_commentsSettings; - QScopedPointer m_followSymbolUnderCursor; QToolButton *m_preprocessorButton; }; @@ -438,12 +266,12 @@ CPPEditorWidgetPrivate::CPPEditorWidgetPrivate(CPPEditorWidget *q) , m_modelManager(CppModelManagerInterface::instance()) , m_cppEditorDocument(qobject_cast(q->baseTextDocument())) , m_cppEditorOutline(new CppEditorOutline(q)) + , m_cppDocumentationCommentHelper(q) , m_localRenaming(q) , m_highlightRevision(0) , m_referencesRevision(0) , m_referencesCursorPosition(0) , m_declDefLinkFinder(new FunctionDeclDefLinkFinder(q)) - , m_commentsSettings(CppTools::CppToolsSettings::instance()->commentsSettings()) , m_followSymbolUnderCursor(new FollowSymbolUnderCursor(q)) , m_preprocessorButton(0) { @@ -489,11 +317,6 @@ void CPPEditorWidget::ctor() connect(d->m_declDefLinkFinder, SIGNAL(foundLink(QSharedPointer)), this, SLOT(onFunctionDeclDefLinkFound(QSharedPointer))); - connect(CppTools::CppToolsSettings::instance(), - SIGNAL(commentsSettingsChanged(CppTools::CommentsSettings)), - this, - SLOT(onCommentsSettingsChanged(CppTools::CommentsSettings))); - connect(baseTextDocument(), SIGNAL(filePathChanged(QString,QString)), this, SLOT(onFilePathChanged())); @@ -1057,8 +880,10 @@ void CPPEditorWidget::keyPressEvent(QKeyEvent *e) if (d->m_localRenaming.handleKeyPressEvent(e)) return; - if (!handleDocumentationComment(e)) - TextEditor::BaseTextEditorWidget::keyPressEvent(e); + if (d->m_cppDocumentationCommentHelper.handleKeyPressEvent(e)) + return; + + TextEditor::BaseTextEditorWidget::keyPressEvent(e); } Core::IEditor *CPPEditor::duplicate() @@ -1403,107 +1228,11 @@ void CPPEditorWidget::onLocalRenamingProcessKeyPressNormally(QKeyEvent *e) BaseTextEditorWidget::keyPressEvent(e); } -bool CPPEditorWidget::handleDocumentationComment(QKeyEvent *e) -{ - if (!d->m_commentsSettings.m_enableDoxygen - && !d->m_commentsSettings.m_leadingAsterisks) { - return false; - } - - if (e->key() == Qt::Key_Return - || e->key() == Qt::Key_Enter) { - QTextCursor cursor = textCursor(); - if (!autoCompleter()->isInComment(cursor)) - return false; - - // We are interested on two particular cases: - // 1) The cursor is right after a /**, /*!, /// or ///! and the user pressed enter. - // If Doxygen is enabled we need to generate an entire comment block. - // 2) The cursor is already in the middle of a multi-line comment and the user pressed - // enter. If leading asterisk(s) is set we need to write a comment continuation - // with those. - - if (d->m_commentsSettings.m_enableDoxygen - && cursor.positionInBlock() >= 3) { - - const int pos = cursor.position(); - - if (isStartOfDoxygenComment(cursor)) { - CppTools::DoxygenGenerator::DocumentationStyle style - = doxygenStyle(cursor, document()); - - // Check if we're already in a CppStyle Doxygen comment => continuation - // Needs special handling since CppStyle does not have start and end markers - if ((style == CppTools::DoxygenGenerator::CppStyleA - || style == CppTools::DoxygenGenerator::CppStyleB) - && isCppStyleContinuation(cursor)) { - return handleDoxygenCppStyleContinuation(cursor, e); - } - - CppTools::DoxygenGenerator doxygen; - doxygen.setStyle(style); - doxygen.setAddLeadingAsterisks(d->m_commentsSettings.m_leadingAsterisks); - doxygen.setGenerateBrief(d->m_commentsSettings.m_generateBrief); - doxygen.setStartComment(false); - - // Move until we reach any possibly meaningful content. - while (document()->characterAt(cursor.position()).isSpace() - && cursor.movePosition(QTextCursor::NextCharacter)) { - } - - if (!cursor.atEnd()) { - const QString &comment = doxygen.generate(cursor); - if (!comment.isEmpty()) { - cursor.beginEditBlock(); - cursor.setPosition(pos); - cursor.insertText(comment); - cursor.setPosition(pos - 3, QTextCursor::KeepAnchor); - baseTextDocument()->autoIndent(cursor); - cursor.endEditBlock(); - e->accept(); - return true; - } - } - - } - } // right after first doxygen comment - - return handleDoxygenContinuation(cursor, - e, - document(), - d->m_commentsSettings.m_enableDoxygen, - d->m_commentsSettings.m_leadingAsterisks); - } - - return false; -} - -bool CPPEditorWidget::isStartOfDoxygenComment(const QTextCursor &cursor) const -{ - const int pos = cursor.position(); - QString comment = QString(document()->characterAt(pos - 3)) - + document()->characterAt(pos - 2) - + document()->characterAt(pos - 1); - - if ((comment == QLatin1String("/**")) - || (comment == QLatin1String("/*!")) - || (comment == QLatin1String("///")) - || (comment == QLatin1String("//!"))) { - return true; - } - return false; -} - QTextCharFormat CPPEditorWidget::textCharFormat(TextEditor::TextStyle category) { return baseTextDocument()->fontSettings().toTextCharFormat(category); } -void CPPEditorWidget::onCommentsSettingsChanged(const CppTools::CommentsSettings &settings) -{ - d->m_commentsSettings = settings; -} - void CPPEditorWidget::showPreProcessorWidget() { const QString &fileName = editor()->document()->filePath(); diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 71109d3b73e..99aed4ec35a 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -44,11 +44,7 @@ #include namespace CPlusPlus { class Symbol; } - -namespace CppTools { -class SemanticInfo; -class CommentsSettings; -} +namespace CppTools { class SemanticInfo; } namespace CppEditor { namespace Internal { @@ -156,7 +152,6 @@ private slots: void markSymbolsNow(); void performQuickFix(int index); void onRefactorMarkerClicked(const TextEditor::RefactorMarker &marker); - void onCommentsSettingsChanged(const CppTools::CommentsSettings &settings); void abortDeclDefLink(); void onLocalRenamingFinished(); @@ -183,9 +178,6 @@ private: QList createSelectionsFromUses( const QList &uses); - bool handleDocumentationComment(QKeyEvent *e); - bool isStartOfDoxygenComment(const QTextCursor &cursor) const; - private: QScopedPointer d; }; diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro index 6e8ff5552b1..440d4b67549 100644 --- a/src/plugins/cppeditor/cppeditor.pro +++ b/src/plugins/cppeditor/cppeditor.pro @@ -5,6 +5,7 @@ HEADERS += \ cppautocompleter.h \ cppclasswizard.h \ cppcodemodelinspectordialog.h \ + cppdocumentationcommenthelper.h \ cppeditor.h \ cppeditor_global.h \ cppeditordocument.h \ @@ -39,6 +40,7 @@ SOURCES += \ cppautocompleter.cpp \ cppclasswizard.cpp \ cppcodemodelinspectordialog.cpp \ + cppdocumentationcommenthelper.cpp \ cppeditor.cpp \ cppeditordocument.cpp \ cppeditoroutline.cpp \ diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs index 8a80874ef27..3b6979900bc 100644 --- a/src/plugins/cppeditor/cppeditor.qbs +++ b/src/plugins/cppeditor/cppeditor.qbs @@ -22,6 +22,7 @@ QtcPlugin { "cppautocompleter.cpp", "cppautocompleter.h", "cppclasswizard.cpp", "cppclasswizard.h", "cppcodemodelinspectordialog.cpp", "cppcodemodelinspectordialog.h", "cppcodemodelinspectordialog.ui", + "cppdocumentationcommenthelper.cpp", "cppdocumentationcommenthelper.h", "cppeditor.cpp", "cppeditor.h", "cppeditor.qrc", "cppeditor_global.h",