From e3c1179abbd81fda7011e79ae20c10de9573b001 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 6 Nov 2023 13:41:39 +0100 Subject: CppEditor: Manually indent moved comments Using the indenter yields unepected results in certain contexts. Fixes: QTCREATORBUG-29786 Change-Id: Id15eff841d2aa54e7fff65c6bf728516e03f9fc6 Reviewed-by: David Schulz Reviewed-by: Christian Kandeler --- src/plugins/cppeditor/cppquickfixes.cpp | 45 +++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'src/plugins/cppeditor/cppquickfixes.cpp') diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 7f08b96200..012785df34 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; -- cgit v1.2.3