CppEditor: Manually indent moved comments

Using the indenter yields unepected results in certain contexts.

Fixes: QTCREATORBUG-29786
Change-Id: Id15eff841d2aa54e7fff65c6bf728516e03f9fc6
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Christian Kandeler
2023-11-06 13:41:39 +01:00
parent 266f9bc632
commit e3c1179abb
2 changed files with 55 additions and 6 deletions

View File

@@ -9272,7 +9272,9 @@ template<typename T> 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"

View File

@@ -34,10 +34,13 @@
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/editorconfiguration.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/projectmanager.h>
#include <texteditor/tabsettings.h>
#include <utils/algorithm.h>
#include <utils/basetreeview.h>
#include <utils/layoutbuilder.h>
@@ -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;