diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index 0c4a07a2c27..d2cf58ebfb4 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -9272,7 +9272,9 @@ template inline T aFunction() { return T(); } const QByteArrayList headersMemberDecl2Def{R"( class C { - // Member function comment + /** + * \brief Foo::aMember + */ void @aMember(); )", R"( class C { @@ -9285,7 +9287,9 @@ void C::aMember() {} )", R"( #include "file.h" -// Member function comment +/** + * \brief Foo::aMember + */ void C::aMember() {} )"}; QTest::newRow("member function: from decl to def") << headersMemberDecl2Def @@ -9296,13 +9300,17 @@ class C { void aMember(); )", R"( class C { - // Member function comment + /** + * \brief Foo::aMember + */ void aMember(); )"}; const QByteArrayList sourcesMemberDef2Decl{R"( #include "file.h" -// Member function comment +/** + * \brief Foo::aMember + */ void C::aMember() {@} )", R"( #include "file.h" diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 7f08b962009..012785df349 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -34,10 +34,13 @@ #include +#include #include #include #include +#include + #include #include #include @@ -9610,7 +9613,45 @@ private: comments.first(), sourceFile->document()); const int sourceCommentEndPos = sourceTu->getTokenEndPositionInDocument( comments.last(), sourceFile->document()); - const QString functionDoc = sourceFile->textOf(sourceCommentStartPos, sourceCommentEndPos); + + // Manually adjust indentation, as both our built-in indenter and ClangFormat + // are unreliable with regards to comment continuation lines. + auto tabSettings = [](CppRefactoringFilePtr file) { + if (auto editor = file->editor()) + return editor->textDocument()->tabSettings(); + return ProjectExplorer::actualTabSettings(file->filePath(), nullptr); + }; + const TabSettings &sts = tabSettings(sourceFile); + const TabSettings &tts = tabSettings(targetFile); + const QTextBlock insertionBlock = targetFile->document()->findBlock(insertionPos); + const int insertionColumn = tts.columnAt(insertionBlock.text(), + insertionPos - insertionBlock.position()); + const QTextBlock removalBlock = sourceFile->document()->findBlock(sourceCommentStartPos); + const QTextBlock removalBlockEnd = sourceFile->document()->findBlock(sourceCommentEndPos); + const int removalColumn = sts.columnAt(removalBlock.text(), + sourceCommentStartPos - removalBlock.position()); + const int columnOffset = insertionColumn - removalColumn; + QString functionDoc; + if (columnOffset != 0) { + for (QTextBlock block = removalBlock; + block.isValid() && block != removalBlockEnd.next(); + block = block.next()) { + QString text = block.text() + QChar::ParagraphSeparator; + if (block == removalBlockEnd) + text = text.left(sourceCommentEndPos - block.position()); + if (block == removalBlock) { + text = text.mid(sourceCommentStartPos - block.position()); + } else { + int lineIndentColumn = sts.indentationColumn(text) + columnOffset; + text.replace(0, + TabSettings::firstNonSpace(text), + tts.indentationString(0, lineIndentColumn, 0, insertionBlock)); + } + functionDoc += text; + } + } else { + functionDoc = sourceFile->textOf(sourceCommentStartPos, sourceCommentEndPos); + } // Remove comment plus leading and trailing whitespace, including trailing newline. const auto removeAtSource = [&](ChangeSet &changeSet) { @@ -9642,10 +9683,10 @@ private: ChangeSet targetChangeSet; targetChangeSet.insert(insertionPos, functionDoc); targetChangeSet.insert(insertionPos, "\n"); + targetChangeSet.insert(insertionPos, QString(insertionColumn, ' ')); if (targetFile == sourceFile) removeAtSource(targetChangeSet); targetFile->setChangeSet(targetChangeSet); - targetFile->appendIndentRange({insertionPos, insertionPos + int(functionDoc.length())}); const bool targetFileSuccess = targetFile->apply(); if (targetFile == sourceFile || !targetFileSuccess) return;