Editor: Collect indentation for a list of text blocks

Allows the indenter to reuse code formatter structures.

Task-number: QTCREATORBUG-16420
Change-Id: Ie906d7fdcb50798da02ef5b750fb03ae752aadc1
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
David Schulz
2016-08-25 13:25:45 +02:00
parent b97bc4016f
commit 89ff2c1db5
9 changed files with 100 additions and 18 deletions

View File

@@ -186,3 +186,21 @@ CppCodeStyleSettings CppQtStyleIndenter::codeStyleSettings() const
return m_cppCodeStylePreferences->currentCodeStyleSettings(); return m_cppCodeStylePreferences->currentCodeStyleSettings();
return CppCodeStyleSettings(); return CppCodeStyleSettings();
} }
TextEditor::IndentationForBlock
CppQtStyleIndenter::indentationForBlocks(const QVector<QTextBlock> &blocks,
const TextEditor::TabSettings &tabSettings)
{
QtStyleCodeFormatter codeFormatter(tabSettings, codeStyleSettings());
codeFormatter.updateStateUntil(blocks.last());
TextEditor::IndentationForBlock ret;
foreach (QTextBlock block, blocks) {
int indent;
int padding;
codeFormatter.indentFor(block, &indent, &padding);
ret.insert(block.blockNumber(), indent);
}
return ret;
}

View File

@@ -58,6 +58,8 @@ public:
void setCodeStylePreferences(TextEditor::ICodeStylePreferences *preferences) override; void setCodeStylePreferences(TextEditor::ICodeStylePreferences *preferences) override;
void invalidateCache(QTextDocument *doc) override; void invalidateCache(QTextDocument *doc) override;
int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override; int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override;
TextEditor::IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
const TextEditor::TabSettings &tabSettings) override;
private: private:
CppCodeStyleSettings codeStyleSettings() const; CppCodeStyleSettings codeStyleSettings() const;
CppCodeStylePreferences *m_cppCodeStylePreferences; CppCodeStylePreferences *m_cppCodeStylePreferences;

View File

@@ -124,5 +124,24 @@ int GlslIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSettin
return indent; return indent;
} }
TextEditor::IndentationForBlock
GlslIndenter::indentationForBlocks(const QVector<QTextBlock> &blocks,
const TextEditor::TabSettings &tabSettings)
{
CppTools::QtStyleCodeFormatter codeFormatter(tabSettings,
CppTools::CppToolsSettings::instance()->cppCodeStyle()->codeStyleSettings());
codeFormatter.updateStateUntil(blocks.last());
TextEditor::IndentationForBlock ret;
foreach (QTextBlock block, blocks) {
int indent;
int padding;
codeFormatter.indentFor(block, &indent, &padding);
ret.insert(block.blockNumber(), indent);
}
return ret;
}
} // namespace Internal } // namespace Internal
} // namespace GlslEditor } // namespace GlslEditor

View File

@@ -48,6 +48,8 @@ public:
const TextEditor::TabSettings &tabSettings) override; const TextEditor::TabSettings &tabSettings) override;
int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override; int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override;
TextEditor::IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
const TextEditor::TabSettings &tabSettings) override;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -90,3 +90,19 @@ int Indenter::indentFor(const QTextBlock &block,
codeFormatter.updateStateUntil(block); codeFormatter.updateStateUntil(block);
return codeFormatter.indentFor(block); return codeFormatter.indentFor(block);
} }
TextEditor::IndentationForBlock
Indenter::indentationForBlocks(const QVector<QTextBlock> &blocks,
const TextEditor::TabSettings &tabSettings)
{
QmlJSTools::CreatorCodeFormatter codeFormatter(tabSettings);
codeFormatter.updateStateUntil(blocks.last());
TextEditor::IndentationForBlock ret;
foreach (QTextBlock block, blocks)
ret.insert(block.blockNumber(), codeFormatter.indentFor(block));
return ret;
}

View File

@@ -46,6 +46,8 @@ public:
void invalidateCache(QTextDocument *doc) override; void invalidateCache(QTextDocument *doc) override;
int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override; int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override;
TextEditor::IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
const TextEditor::TabSettings &tabSettings) override;
}; };
} // Internal } // Internal

View File

@@ -118,3 +118,12 @@ int Indenter::indentFor(const QTextBlock &block, const TabSettings &tabSettings)
Q_UNUSED(tabSettings) Q_UNUSED(tabSettings)
return -1; return -1;
} }
IndentationForBlock Indenter::indentationForBlocks(const QVector<QTextBlock> &blocks,
const TabSettings &tabSettings)
{
IndentationForBlock ret;
foreach (QTextBlock block, blocks)
ret.insert(block.blockNumber(), indentFor(block, tabSettings));
return ret;
}

View File

@@ -27,6 +27,8 @@
#include "texteditor_global.h" #include "texteditor_global.h"
#include <QMap>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QTextDocument; class QTextDocument;
class QTextCursor; class QTextCursor;
@@ -39,6 +41,8 @@ namespace TextEditor {
class ICodeStylePreferences; class ICodeStylePreferences;
class TabSettings; class TabSettings;
using IndentationForBlock = QMap<int, int>;
class TEXTEDITOR_EXPORT Indenter class TEXTEDITOR_EXPORT Indenter
{ {
public: public:
@@ -69,6 +73,10 @@ public:
virtual void invalidateCache(QTextDocument *doc); virtual void invalidateCache(QTextDocument *doc);
virtual int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings); virtual int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings);
// Expects a list of blocks in order of occurrence in the document.
virtual IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
const TextEditor::TabSettings &tabSettings);
}; };
} // namespace TextEditor } // namespace TextEditor

View File

@@ -764,29 +764,35 @@ void TextDocument::cleanWhitespace(QTextCursor &cursor, bool cleanIndentation, b
if (cursor.hasSelection()) if (cursor.hasSelection())
end = d->m_document.findBlock(cursor.selectionEnd()-1).next(); end = d->m_document.findBlock(cursor.selectionEnd()-1).next();
QVector<QTextBlock> blocks;
while (block.isValid() && block != end) { while (block.isValid() && block != end) {
if (inEntireDocument || block.revision() != documentLayout->lastSaveRevision)
blocks.append(block);
block = block.next();
}
if (blocks.isEmpty())
return;
if (inEntireDocument || block.revision() != documentLayout->lastSaveRevision) { const IndentationForBlock &indentations =
d->m_indenter->indentationForBlocks(blocks, d->m_tabSettings);
QString blockText = block.text(); foreach (block, blocks) {
d->m_tabSettings.removeTrailingWhitespace(cursor, block); QString blockText = block.text();
const int indent = d->m_indenter->indentFor(block, d->m_tabSettings); d->m_tabSettings.removeTrailingWhitespace(cursor, block);
if (cleanIndentation && !d->m_tabSettings.isIndentationClean(block, indent)) { const int indent = indentations[block.blockNumber()];
cursor.setPosition(block.position()); if (cleanIndentation && !d->m_tabSettings.isIndentationClean(block, indent)) {
int firstNonSpace = d->m_tabSettings.firstNonSpace(blockText); cursor.setPosition(block.position());
if (firstNonSpace == blockText.length()) { int firstNonSpace = d->m_tabSettings.firstNonSpace(blockText);
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); if (firstNonSpace == blockText.length()) {
cursor.removeSelectedText(); cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
} else { cursor.removeSelectedText();
int column = d->m_tabSettings.columnAt(blockText, firstNonSpace); } else {
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, firstNonSpace); int column = d->m_tabSettings.columnAt(blockText, firstNonSpace);
QString indentationString = d->m_tabSettings.indentationString(0, column, column - indent, block); cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, firstNonSpace);
cursor.insertText(indentationString); QString indentationString = d->m_tabSettings.indentationString(0, column, column - indent, block);
} cursor.insertText(indentationString);
} }
} }
block = block.next();
} }
} }