forked from qt-creator/qt-creator
ClangFormat: Do not format text but indent only
Provide the separate infrastructure for the formatting but use it only when QTC_FORMAT_INSTEAD_OF_INDENT is provided in run environment. Fixes: QTCREATORBUG-21447 Fixes: QTCREATORBUG-21459 Change-Id: I1ad6fe23f5de17016c0c7b18749c6977fc03a22b Reviewed-by: Marco Bubke <marco.bubke@qt.io> Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -65,18 +65,20 @@ void adjustFormatStyleForLineBreak(format::FormatStyle &style)
|
|||||||
style.KeepLineBreaksForNonEmptyLines = true;
|
style.KeepLineBreaksForNonEmptyLines = true;
|
||||||
#endif
|
#endif
|
||||||
style.MaxEmptyLinesToKeep = 2;
|
style.MaxEmptyLinesToKeep = 2;
|
||||||
|
style.SortIncludes = false;
|
||||||
|
style.SortUsingDeclarations = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Replacements filteredReplacements(const Replacements &replacements,
|
Replacements filteredReplacements(const Replacements &replacements,
|
||||||
int offset,
|
int offset,
|
||||||
int lengthForFilter,
|
int extraOffsetToAdd,
|
||||||
int extraOffsetToAdd)
|
bool onlyIndention)
|
||||||
{
|
{
|
||||||
Replacements filtered;
|
Replacements filtered;
|
||||||
for (const Replacement &replacement : replacements) {
|
for (const Replacement &replacement : replacements) {
|
||||||
int replacementOffset = static_cast<int>(replacement.getOffset());
|
int replacementOffset = static_cast<int>(replacement.getOffset());
|
||||||
if (replacementOffset >= offset + lengthForFilter)
|
if (onlyIndention && replacementOffset != offset - 1)
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
if (replacementOffset + 1 >= offset)
|
if (replacementOffset + 1 >= offset)
|
||||||
replacementOffset += extraOffsetToAdd;
|
replacementOffset += extraOffsetToAdd;
|
||||||
@@ -138,7 +140,7 @@ void modifyToIndentEmptyLines(QByteArray &buffer, int &offset, int &length, cons
|
|||||||
{
|
{
|
||||||
const QString blockText = block.text().trimmed();
|
const QString blockText = block.text().trimmed();
|
||||||
const bool closingParenBlock = blockText.startsWith(')');
|
const bool closingParenBlock = blockText.startsWith(')');
|
||||||
if (length != 0 && !closingParenBlock)
|
if (!blockText.isEmpty() && !closingParenBlock)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//This extra text works for the most cases.
|
//This extra text works for the most cases.
|
||||||
@@ -207,8 +209,8 @@ Replacements replacements(const Utils::FileName &fileName,
|
|||||||
|
|
||||||
return filteredReplacements(replacements,
|
return filteredReplacements(replacements,
|
||||||
utf8Offset,
|
utf8Offset,
|
||||||
utf8Length,
|
extraOffset,
|
||||||
extraOffset);
|
block);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::LineColumn utf16LineColumn(const QTextBlock &block,
|
Utils::LineColumn utf16LineColumn(const QTextBlock &block,
|
||||||
@@ -216,17 +218,14 @@ Utils::LineColumn utf16LineColumn(const QTextBlock &block,
|
|||||||
const QByteArray &utf8Buffer,
|
const QByteArray &utf8Buffer,
|
||||||
int utf8Offset)
|
int utf8Offset)
|
||||||
{
|
{
|
||||||
// Do not search if the offset is less - we are not interested.
|
|
||||||
if (utf8Offset < blockOffsetUtf8 - 1)
|
|
||||||
return Utils::LineColumn();
|
|
||||||
|
|
||||||
// If lastIndexOf('\n') returns -1 then we are fine to add 1 and get 0 offset.
|
// If lastIndexOf('\n') returns -1 then we are fine to add 1 and get 0 offset.
|
||||||
const int lineStartUtf8Offset = utf8Buffer.lastIndexOf('\n', utf8Offset - 1) + 1;
|
const int lineStartUtf8Offset = utf8Buffer.lastIndexOf('\n', utf8Offset - 1) + 1;
|
||||||
|
|
||||||
int line = block.blockNumber() + 1; // Init with the line corresponding the block.
|
int line = block.blockNumber() + 1; // Init with the line corresponding the block.
|
||||||
if (utf8Offset == blockOffsetUtf8 - 1) {
|
|
||||||
// Our offset is the end of the previous line
|
if (utf8Offset < blockOffsetUtf8) {
|
||||||
--line;
|
line -= static_cast<int>(std::count(utf8Buffer.begin() + lineStartUtf8Offset,
|
||||||
|
utf8Buffer.begin() + blockOffsetUtf8,
|
||||||
|
'\n'));
|
||||||
} else {
|
} else {
|
||||||
line += static_cast<int>(std::count(utf8Buffer.begin() + blockOffsetUtf8,
|
line += static_cast<int>(std::count(utf8Buffer.begin() + blockOffsetUtf8,
|
||||||
utf8Buffer.begin() + lineStartUtf8Offset,
|
utf8Buffer.begin() + lineStartUtf8Offset,
|
||||||
@@ -333,41 +332,53 @@ void ClangFormatIndenter::indent(QTextDocument *doc,
|
|||||||
const QTextCursor &cursor,
|
const QTextCursor &cursor,
|
||||||
const QChar &typedChar,
|
const QChar &typedChar,
|
||||||
const TabSettings &tabSettings,
|
const TabSettings &tabSettings,
|
||||||
bool autoTriggered)
|
bool /*autoTriggered*/)
|
||||||
{
|
{
|
||||||
if (typedChar == QChar::Null && (cursor.hasSelection() || !autoTriggered)) {
|
if (cursor.hasSelection()) {
|
||||||
TextEditorWidget *editor = TextEditorWidget::currentTextEditorWidget();
|
QTextBlock currentBlock = doc->findBlock(cursor.selectionStart());
|
||||||
if (!editor)
|
while (currentBlock.isValid() && currentBlock.position() < cursor.selectionEnd()) {
|
||||||
return;
|
indentBlock(doc, currentBlock, typedChar, tabSettings);
|
||||||
const Utils::FileName fileName = editor->textDocument()->filePath();
|
currentBlock = currentBlock.next();
|
||||||
int utf8Offset;
|
|
||||||
int utf8Length;
|
|
||||||
const QByteArray buffer = doc->toPlainText().toUtf8();
|
|
||||||
if (cursor.hasSelection()) {
|
|
||||||
const QTextBlock start = doc->findBlock(cursor.selectionStart());
|
|
||||||
const QTextBlock end = doc->findBlock(cursor.selectionEnd());
|
|
||||||
utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, start.blockNumber() + 1);
|
|
||||||
QTC_ASSERT(utf8Offset >= 0, return;);
|
|
||||||
utf8Length = selectedLines(doc, start, end).toUtf8().size();
|
|
||||||
applyReplacements(start,
|
|
||||||
utf8Offset,
|
|
||||||
buffer,
|
|
||||||
replacements(fileName, buffer, utf8Offset, utf8Length));
|
|
||||||
} else {
|
|
||||||
const QTextBlock block = cursor.block();
|
|
||||||
utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, block.blockNumber() + 1);
|
|
||||||
QTC_ASSERT(utf8Offset >= 0, return;);
|
|
||||||
utf8Length = block.text().toUtf8().size();
|
|
||||||
applyReplacements(block,
|
|
||||||
utf8Offset,
|
|
||||||
buffer,
|
|
||||||
replacements(fileName, buffer, utf8Offset, utf8Length));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
indentBlock(doc, cursor.block(), typedChar, tabSettings);
|
indentBlock(doc, cursor.block(), typedChar, tabSettings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClangFormatIndenter::format(QTextDocument *doc,
|
||||||
|
const QTextCursor &cursor,
|
||||||
|
const TextEditor::TabSettings &/*tabSettings*/)
|
||||||
|
{
|
||||||
|
TextEditorWidget *editor = TextEditorWidget::currentTextEditorWidget();
|
||||||
|
if (!editor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Utils::FileName fileName = editor->textDocument()->filePath();
|
||||||
|
int utf8Offset;
|
||||||
|
int utf8Length;
|
||||||
|
const QByteArray buffer = doc->toPlainText().toUtf8();
|
||||||
|
if (cursor.hasSelection()) {
|
||||||
|
const QTextBlock start = doc->findBlock(cursor.selectionStart());
|
||||||
|
const QTextBlock end = doc->findBlock(cursor.selectionEnd());
|
||||||
|
utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, start.blockNumber() + 1);
|
||||||
|
QTC_ASSERT(utf8Offset >= 0, return;);
|
||||||
|
utf8Length = selectedLines(doc, start, end).toUtf8().size();
|
||||||
|
applyReplacements(start,
|
||||||
|
utf8Offset,
|
||||||
|
buffer,
|
||||||
|
replacements(fileName, buffer, utf8Offset, utf8Length));
|
||||||
|
} else {
|
||||||
|
const QTextBlock block = cursor.block();
|
||||||
|
utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, block.blockNumber() + 1);
|
||||||
|
QTC_ASSERT(utf8Offset >= 0, return;);
|
||||||
|
utf8Length = block.text().toUtf8().size();
|
||||||
|
applyReplacements(block,
|
||||||
|
utf8Offset,
|
||||||
|
buffer,
|
||||||
|
replacements(fileName, buffer, utf8Offset, utf8Length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ClangFormatIndenter::reindent(QTextDocument *doc,
|
void ClangFormatIndenter::reindent(QTextDocument *doc,
|
||||||
const QTextCursor &cursor,
|
const QTextCursor &cursor,
|
||||||
const TabSettings &tabSettings)
|
const TabSettings &tabSettings)
|
||||||
@@ -391,12 +402,11 @@ void ClangFormatIndenter::indentBlock(QTextDocument *doc,
|
|||||||
const QByteArray buffer = doc->toPlainText().toUtf8();
|
const QByteArray buffer = doc->toPlainText().toUtf8();
|
||||||
const int utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, block.blockNumber() + 1);
|
const int utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, block.blockNumber() + 1);
|
||||||
QTC_ASSERT(utf8Offset >= 0, return;);
|
QTC_ASSERT(utf8Offset >= 0, return;);
|
||||||
const int utf8Length = block.text().toUtf8().size();
|
|
||||||
|
|
||||||
applyReplacements(block,
|
applyReplacements(block,
|
||||||
utf8Offset,
|
utf8Offset,
|
||||||
buffer,
|
buffer,
|
||||||
replacements(fileName, buffer, utf8Offset, utf8Length, &block, typedChar));
|
replacements(fileName, buffer, utf8Offset, 0, &block, typedChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
int ClangFormatIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSettings &)
|
int ClangFormatIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSettings &)
|
||||||
@@ -411,9 +421,8 @@ int ClangFormatIndenter::indentFor(const QTextBlock &block, const TextEditor::Ta
|
|||||||
const QByteArray buffer = doc->toPlainText().toUtf8();
|
const QByteArray buffer = doc->toPlainText().toUtf8();
|
||||||
const int utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, block.blockNumber() + 1);
|
const int utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, block.blockNumber() + 1);
|
||||||
QTC_ASSERT(utf8Offset >= 0, return 0;);
|
QTC_ASSERT(utf8Offset >= 0, return 0;);
|
||||||
const int utf8Length = block.text().toUtf8().size();
|
|
||||||
|
|
||||||
Replacements toReplace = replacements(fileName, buffer, utf8Offset, utf8Length, &block);
|
Replacements toReplace = replacements(fileName, buffer, utf8Offset, 0, &block);
|
||||||
|
|
||||||
if (toReplace.empty())
|
if (toReplace.empty())
|
||||||
return -1;
|
return -1;
|
||||||
|
@@ -40,6 +40,9 @@ public:
|
|||||||
void reindent(QTextDocument *doc,
|
void reindent(QTextDocument *doc,
|
||||||
const QTextCursor &cursor,
|
const QTextCursor &cursor,
|
||||||
const TextEditor::TabSettings &tabSettings) override;
|
const TextEditor::TabSettings &tabSettings) override;
|
||||||
|
void format(QTextDocument *doc,
|
||||||
|
const QTextCursor &cursor,
|
||||||
|
const TextEditor::TabSettings &tabSettings) override;
|
||||||
void indentBlock(QTextDocument *doc,
|
void indentBlock(QTextDocument *doc,
|
||||||
const QTextBlock &block,
|
const QTextBlock &block,
|
||||||
const QChar &typedChar,
|
const QChar &typedChar,
|
||||||
|
@@ -104,6 +104,13 @@ void Indenter::reindent(QTextDocument *doc, const QTextCursor &cursor, const Tab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Indenter::format(QTextDocument *doc,
|
||||||
|
const QTextCursor &cursor,
|
||||||
|
const TabSettings &tabSettings)
|
||||||
|
{
|
||||||
|
indent(doc, cursor, QChar::Null, tabSettings);
|
||||||
|
}
|
||||||
|
|
||||||
void Indenter::setCodeStylePreferences(ICodeStylePreferences *)
|
void Indenter::setCodeStylePreferences(ICodeStylePreferences *)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@@ -67,6 +67,11 @@ public:
|
|||||||
const TabSettings &tabSettings,
|
const TabSettings &tabSettings,
|
||||||
bool autoTriggered = true);
|
bool autoTriggered = true);
|
||||||
|
|
||||||
|
// By default just calls indent with default settings.
|
||||||
|
virtual void format(QTextDocument *doc,
|
||||||
|
const QTextCursor &cursor,
|
||||||
|
const TabSettings &tabSettings);
|
||||||
|
|
||||||
// Reindent at cursor. Selection will be adjusted according to the indentation
|
// Reindent at cursor. Selection will be adjusted according to the indentation
|
||||||
// change of the first block.
|
// change of the first block.
|
||||||
virtual void reindent(QTextDocument *doc, const QTextCursor &cursor, const TabSettings &tabSettings);
|
virtual void reindent(QTextDocument *doc, const QTextCursor &cursor, const TabSettings &tabSettings);
|
||||||
|
@@ -426,6 +426,11 @@ void TextDocument::autoReindent(const QTextCursor &cursor)
|
|||||||
d->m_indenter->reindent(&d->m_document, cursor, tabSettings());
|
d->m_indenter->reindent(&d->m_document, cursor, tabSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextDocument::autoFormat(const QTextCursor &cursor)
|
||||||
|
{
|
||||||
|
d->m_indenter->format(&d->m_document, cursor, tabSettings());
|
||||||
|
}
|
||||||
|
|
||||||
QTextCursor TextDocument::indent(const QTextCursor &cursor, bool blockSelection, int column,
|
QTextCursor TextDocument::indent(const QTextCursor &cursor, bool blockSelection, int column,
|
||||||
int *offset)
|
int *offset)
|
||||||
{
|
{
|
||||||
|
@@ -90,6 +90,7 @@ public:
|
|||||||
void autoIndent(const QTextCursor &cursor, QChar typedChar = QChar::Null,
|
void autoIndent(const QTextCursor &cursor, QChar typedChar = QChar::Null,
|
||||||
bool autoTriggered = true);
|
bool autoTriggered = true);
|
||||||
void autoReindent(const QTextCursor &cursor);
|
void autoReindent(const QTextCursor &cursor);
|
||||||
|
void autoFormat(const QTextCursor &cursor);
|
||||||
QTextCursor indent(const QTextCursor &cursor, bool blockSelection = false, int column = 0,
|
QTextCursor indent(const QTextCursor &cursor, bool blockSelection = false, int column = 0,
|
||||||
int *offset = nullptr);
|
int *offset = nullptr);
|
||||||
QTextCursor unindent(const QTextCursor &cursor, bool blockSelection = false, int column = 0,
|
QTextCursor unindent(const QTextCursor &cursor, bool blockSelection = false, int column = 0,
|
||||||
|
@@ -7132,11 +7132,21 @@ void TextEditorWidget::setIfdefedOutBlocks(const QList<BlockRange> &blocks)
|
|||||||
documentLayout->requestUpdate();
|
documentLayout->requestUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool applyFormattingInsteadOfIndentation()
|
||||||
|
{
|
||||||
|
constexpr const char option[] = "QTC_FORMAT_INSTEAD_OF_INDENT";
|
||||||
|
return qEnvironmentVariableIsSet(option);
|
||||||
|
}
|
||||||
|
|
||||||
void TextEditorWidget::format()
|
void TextEditorWidget::format()
|
||||||
{
|
{
|
||||||
|
static bool formattingInsteadOfIndentation = applyFormattingInsteadOfIndentation();
|
||||||
QTextCursor cursor = textCursor();
|
QTextCursor cursor = textCursor();
|
||||||
cursor.beginEditBlock();
|
cursor.beginEditBlock();
|
||||||
d->m_document->autoIndent(cursor, QChar::Null, false);
|
if (formattingInsteadOfIndentation)
|
||||||
|
d->m_document->autoFormat(cursor);
|
||||||
|
else
|
||||||
|
d->m_document->autoIndent(cursor);
|
||||||
cursor.endEditBlock();
|
cursor.endEditBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user