aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorDavid Schulz <david.schulz@theqtcompany.com>2016-01-13 14:32:23 +0100
committerDavid Schulz <david.schulz@theqtcompany.com>2016-02-24 12:03:12 +0000
commit9aa51d4857702c22d359014356d06c9d92677904 (patch)
tree79d73774ac0541e65fbe03e44592a43fc95ba152 /src/plugins
parentbc921b46a2946294b467e1d2bcafb147ee77361a (diff)
Editor: Fix whitespace cleaning.
Task-number: QTCREATORBUG-7994 Change-Id: I6c197ccc3a148555018e8f8184d116c88d7ea400 Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com> Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/android/javaindenter.cpp46
-rw-r--r--src/plugins/android/javaindenter.h18
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeindenter.cpp33
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeindenter.h3
-rw-r--r--src/plugins/cpptools/cppqtstyleindenter.cpp12
-rw-r--r--src/plugins/cpptools/cppqtstyleindenter.h25
-rw-r--r--src/plugins/glsleditor/glslindenter.cpp13
-rw-r--r--src/plugins/glsleditor/glslindenter.h2
-rw-r--r--src/plugins/pythoneditor/tools/pythonindenter.cpp52
-rw-r--r--src/plugins/pythoneditor/tools/pythonindenter.h13
-rw-r--r--src/plugins/qmljstools/qmljsindenter.cpp17
-rw-r--r--src/plugins/qmljstools/qmljsindenter.h18
-rw-r--r--src/plugins/texteditor/indenter.cpp14
-rw-r--r--src/plugins/texteditor/indenter.h2
-rw-r--r--src/plugins/texteditor/normalindenter.cpp38
-rw-r--r--src/plugins/texteditor/normalindenter.h9
-rw-r--r--src/plugins/texteditor/tabsettings.cpp69
-rw-r--r--src/plugins/texteditor/tabsettings.h18
-rw-r--r--src/plugins/texteditor/textdocument.cpp11
-rw-r--r--src/plugins/texteditor/texteditor.cpp6
-rw-r--r--src/plugins/texteditor/texteditor_test.cpp130
-rw-r--r--src/plugins/texteditor/texteditorplugin.h3
22 files changed, 349 insertions, 203 deletions
diff --git a/src/plugins/android/javaindenter.cpp b/src/plugins/android/javaindenter.cpp
index 5b867928fa2..21c99609add 100644
--- a/src/plugins/android/javaindenter.cpp
+++ b/src/plugins/android/javaindenter.cpp
@@ -48,40 +48,36 @@ bool JavaIndenter::isElectricCharacter(const QChar &ch) const
}
void JavaIndenter::indentBlock(QTextDocument *doc,
- const QTextBlock &block,
- const QChar &typedChar,
- const TextEditor::TabSettings &tabSettings)
+ const QTextBlock &block,
+ const QChar &typedChar,
+ const TextEditor::TabSettings &tabSettings)
{
- // At beginning: Leave as is.
- if (block == doc->begin())
- return;
-
- const int tabsize = tabSettings.m_indentSize;
+ Q_UNUSED(doc);
+ int indent = indentFor(block, tabSettings);
+ if (typedChar == QLatin1Char('}'))
+ indent -= tabSettings.m_indentSize;
+ tabSettings.indentLine(block, qMax(0, indent));
+}
+int JavaIndenter::indentFor(const QTextBlock &block,
+ const TextEditor::TabSettings &tabSettings)
+{
QTextBlock previous = block.previous();
+ if (!previous.isValid())
+ return 0;
+
QString previousText = previous.text();
while (previousText.trimmed().isEmpty()) {
previous = previous.previous();
- if (previous == doc->begin())
- return;
+ if (!previous.isValid())
+ return 0;
previousText = previous.text();
}
- int adjust = 0;
- if (previousText.contains(QLatin1Char('{')))
- adjust = tabsize;
+ int indent = tabSettings.indentationColumn(previousText);
- if (block.text().contains(QLatin1Char('}')) || typedChar == QLatin1Char('}'))
- adjust += -tabsize;
+ int adjust = previousText.count(QLatin1Char('{')) - previousText.count(QLatin1Char('}'));
+ adjust *= tabSettings.m_indentSize;
- // Count the indentation of the previous line.
- int i = 0;
- while (i < previousText.size()) {
- if (!previousText.at(i).isSpace()) {
- tabSettings.indentLine(block, tabSettings.columnAt(previousText, i)
- + adjust);
- break;
- }
- ++i;
- }
+ return qMax(0, indent + adjust);
}
diff --git a/src/plugins/android/javaindenter.h b/src/plugins/android/javaindenter.h
index 46b5ccdddb1..9be0b47a954 100644
--- a/src/plugins/android/javaindenter.h
+++ b/src/plugins/android/javaindenter.h
@@ -34,16 +34,18 @@ class JavaIndenter : public TextEditor::Indenter
{
public:
JavaIndenter();
- virtual ~JavaIndenter();
+ ~JavaIndenter() override;
- bool isElectricCharacter(const QChar &ch) const;
+ bool isElectricCharacter(const QChar &ch) const override;
- virtual void indentBlock(QTextDocument *doc,
- const QTextBlock &block,
- const QChar &typedChar,
- const TextEditor::TabSettings &tabSettings);
+ void indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ const TextEditor::TabSettings &tabSettings) override;
+
+ int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override;
};
-}
-}
+} // namespace Internal
+} // namespace Android
#endif // JAVAINDENTER_H
diff --git a/src/plugins/cmakeprojectmanager/cmakeindenter.cpp b/src/plugins/cmakeprojectmanager/cmakeindenter.cpp
index 9c582313466..882f0277a67 100644
--- a/src/plugins/cmakeprojectmanager/cmakeindenter.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeindenter.cpp
@@ -98,34 +98,29 @@ static int paranthesesLevel(const QString &line)
return -1;
}
-void CMakeIndenter::indentBlock(QTextDocument *doc, const QTextBlock &block, const QChar &typedChar, const TextEditor::TabSettings &tabSettings)
+int CMakeIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings)
{
- Q_UNUSED(doc)
- Q_UNUSED(typedChar)
-
QTextBlock previousBlock = block.previous();
// find the next previous block that is non-empty (contains non-whitespace characters)
while (previousBlock.isValid() && lineIsEmpty(previousBlock.text()))
previousBlock = previousBlock.previous();
- if (previousBlock.isValid()) {
- const QString previousLine = previousBlock.text();
- const QString currentLine = block.text();
- int indentation = tabSettings.indentationColumn(previousLine);
+ if (!previousBlock.isValid())
+ return 0;
- if (lineStartsBlock(previousLine))
- indentation += tabSettings.m_indentSize;
- if (lineEndsBlock(currentLine))
- indentation = qMax(0, indentation - tabSettings.m_indentSize);
+ const QString previousLine = previousBlock.text();
+ const QString currentLine = block.text();
+ int indentation = tabSettings.indentationColumn(previousLine);
- // increase/decrease/keep the indentation level depending on if we have more opening or closing parantheses
- indentation = qMax(0, indentation + tabSettings.m_indentSize * paranthesesLevel(previousLine));
+ if (lineStartsBlock(previousLine))
+ indentation += tabSettings.m_indentSize;
+ if (lineEndsBlock(currentLine))
+ indentation = qMax(0, indentation - tabSettings.m_indentSize);
- tabSettings.indentLine(block, indentation);
- } else {
- // First line in whole document
- tabSettings.indentLine(block, 0);
- }
+ // increase/decrease/keep the indentation level depending on if we have more opening or closing parantheses
+ return qMax(0, indentation + tabSettings.m_indentSize * paranthesesLevel(previousLine));
}
} // namespace Internal
} // namespace CMakeProjectManager
+
+
diff --git a/src/plugins/cmakeprojectmanager/cmakeindenter.h b/src/plugins/cmakeprojectmanager/cmakeindenter.h
index 3b2b2a27b4a..a47bdcced5f 100644
--- a/src/plugins/cmakeprojectmanager/cmakeindenter.h
+++ b/src/plugins/cmakeprojectmanager/cmakeindenter.h
@@ -36,7 +36,8 @@ class CMAKE_EXPORT CMakeIndenter : public TextEditor::Indenter
{
public:
bool isElectricCharacter(const QChar &ch) const override;
- void indentBlock(QTextDocument *doc, const QTextBlock &block, const QChar &typedChar, const TextEditor::TabSettings &tabSettings) override;
+
+ int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override;
};
} // namespace Internal
diff --git a/src/plugins/cpptools/cppqtstyleindenter.cpp b/src/plugins/cpptools/cppqtstyleindenter.cpp
index ea46e242ff6..e1596c60c69 100644
--- a/src/plugins/cpptools/cppqtstyleindenter.cpp
+++ b/src/plugins/cpptools/cppqtstyleindenter.cpp
@@ -168,6 +168,18 @@ void CppQtStyleIndenter::invalidateCache(QTextDocument *doc)
formatter.invalidateCache(doc);
}
+int CppQtStyleIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings)
+{
+ QtStyleCodeFormatter codeFormatter(tabSettings, codeStyleSettings());
+
+ codeFormatter.updateStateUntil(block);
+ int indent;
+ int padding;
+ codeFormatter.indentFor(block, &indent, &padding);
+
+ return indent;
+}
+
CppCodeStyleSettings CppQtStyleIndenter::codeStyleSettings() const
{
if (m_cppCodeStylePreferences)
diff --git a/src/plugins/cpptools/cppqtstyleindenter.h b/src/plugins/cpptools/cppqtstyleindenter.h
index 7c77affb4d1..eb3196043ab 100644
--- a/src/plugins/cpptools/cppqtstyleindenter.h
+++ b/src/plugins/cpptools/cppqtstyleindenter.h
@@ -43,21 +43,22 @@ class CPPTOOLS_EXPORT CppQtStyleIndenter : public TextEditor::Indenter
{
public:
CppQtStyleIndenter();
- virtual ~CppQtStyleIndenter();
+ ~CppQtStyleIndenter() override;
- virtual bool isElectricCharacter(const QChar &ch) const;
- virtual void indentBlock(QTextDocument *doc,
- const QTextBlock &block,
- const QChar &typedChar,
- const TextEditor::TabSettings &tabSettings);
+ bool isElectricCharacter(const QChar &ch) const override;
+ void indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ const TextEditor::TabSettings &tabSettings) override;
- virtual void indent(QTextDocument *doc,
- const QTextCursor &cursor,
- const QChar &typedChar,
- const TextEditor::TabSettings &tabSettings);
+ void indent(QTextDocument *doc,
+ const QTextCursor &cursor,
+ const QChar &typedChar,
+ const TextEditor::TabSettings &tabSettings) override;
- virtual void setCodeStylePreferences(TextEditor::ICodeStylePreferences *preferences);
- virtual void invalidateCache(QTextDocument *doc);
+ void setCodeStylePreferences(TextEditor::ICodeStylePreferences *preferences) override;
+ void invalidateCache(QTextDocument *doc) override;
+ int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override;
private:
CppCodeStyleSettings codeStyleSettings() const;
CppCodeStylePreferences *m_cppCodeStylePreferences;
diff --git a/src/plugins/glsleditor/glslindenter.cpp b/src/plugins/glsleditor/glslindenter.cpp
index fd4698ac6c3..33aa8470649 100644
--- a/src/plugins/glsleditor/glslindenter.cpp
+++ b/src/plugins/glsleditor/glslindenter.cpp
@@ -111,5 +111,18 @@ void GlslIndenter::indent(QTextDocument *doc,
}
}
+int GlslIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings)
+{
+ CppTools::QtStyleCodeFormatter codeFormatter(tabSettings,
+ CppTools::CppToolsSettings::instance()->cppCodeStyle()->codeStyleSettings());
+
+ codeFormatter.updateStateUntil(block);
+ int indent;
+ int padding;
+ codeFormatter.indentFor(block, &indent, &padding);
+
+ return indent;
+}
+
} // namespace Internal
} // namespace GlslEditor
diff --git a/src/plugins/glsleditor/glslindenter.h b/src/plugins/glsleditor/glslindenter.h
index 98f93feebfd..98ba0002cac 100644
--- a/src/plugins/glsleditor/glslindenter.h
+++ b/src/plugins/glsleditor/glslindenter.h
@@ -47,6 +47,8 @@ public:
const QTextCursor &cursor,
const QChar &typedChar,
const TextEditor::TabSettings &tabSettings);
+
+ int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override;
};
} // namespace Internal
diff --git a/src/plugins/pythoneditor/tools/pythonindenter.cpp b/src/plugins/pythoneditor/tools/pythonindenter.cpp
index 1d09f9f9805..819772c74cf 100644
--- a/src/plugins/pythoneditor/tools/pythonindenter.cpp
+++ b/src/plugins/pythoneditor/tools/pythonindenter.cpp
@@ -32,9 +32,6 @@
namespace PythonEditor {
-// Tab size hardcoded as PEP8 style guide requires, but can be moved to settings
-static const int TAB_SIZE = 4;
-
PythonIndenter::PythonIndenter()
{
m_jumpKeywords << QLatin1String("return")
@@ -59,39 +56,21 @@ bool PythonIndenter::isElectricCharacter(const QChar &ch) const
return (ch == QLatin1Char(':'));
}
-/**
- * @brief Indents one block (i.e. one line) of code
- * @param doc Unused
- * @param block Block that represents line
- * @param typedChar Unused
- * @param tabSettings An IDE tabulation settings
- *
- * Usually this function called once when you begin new line of code by pressing
- * Enter. If Indenter reimplements indent() function, than indentBlock() may be
- * called in other cases.
- */
-void PythonIndenter::indentBlock(QTextDocument *document,
- const QTextBlock &block,
- const QChar &typedChar,
- const TextEditor::TabSettings &settings)
+int PythonIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings)
{
- Q_UNUSED(document);
- Q_UNUSED(typedChar);
QTextBlock previousBlock = block.previous();
- if (previousBlock.isValid()) {
- QString previousLine = previousBlock.text();
- int indentation = settings.indentationColumn(previousLine);
-
- if (isElectricLine(previousLine))
- indentation += TAB_SIZE;
- else
- indentation = qMax<int>(0, indentation + getIndentDiff(previousLine));
-
- settings.indentLine(block, indentation);
- } else {
- // First line in whole document
- settings.indentLine(block, 0);
- }
+ if (!previousBlock.isValid())
+ return 0;
+
+ QString previousLine = previousBlock.text();
+ int indentation = tabSettings.indentationColumn(previousLine);
+
+ if (isElectricLine(previousLine))
+ indentation += tabSettings.m_indentSize;
+ else
+ indentation = qMax<int>(0, indentation + getIndentDiff(previousLine, tabSettings));
+
+ return indentation;
}
/// @return True if electric character is last non-space character at given string
@@ -109,13 +88,14 @@ bool PythonIndenter::isElectricLine(const QString &line) const
}
/// @return negative indent diff if previous line breaks control flow branch
-int PythonIndenter::getIndentDiff(const QString &previousLine) const
+int PythonIndenter::getIndentDiff(const QString &previousLine,
+ const TextEditor::TabSettings &tabSettings) const
{
Internal::Scanner sc(previousLine.constData(), previousLine.length());
forever {
Internal::FormatToken tk = sc.read();
if ((tk.format() == Internal::Format_Keyword) && m_jumpKeywords.contains(sc.value(tk)))
- return -TAB_SIZE;
+ return -tabSettings.m_indentSize;
if (tk.format() != Internal::Format_Whitespace)
break;
}
diff --git a/src/plugins/pythoneditor/tools/pythonindenter.h b/src/plugins/pythoneditor/tools/pythonindenter.h
index faf73f4ac51..6846aa1ba81 100644
--- a/src/plugins/pythoneditor/tools/pythonindenter.h
+++ b/src/plugins/pythoneditor/tools/pythonindenter.h
@@ -35,17 +35,16 @@ class PythonIndenter : public TextEditor::Indenter
{
public:
PythonIndenter();
- virtual ~PythonIndenter();
+ virtual ~PythonIndenter() override;
- bool isElectricCharacter(const QChar &ch) const;
- void indentBlock(QTextDocument *document,
- const QTextBlock &block,
- const QChar &typedChar,
- const TextEditor::TabSettings &settings);
+ bool isElectricCharacter(const QChar &ch) const override;
+
+ int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override;
protected:
bool isElectricLine(const QString &line) const;
- int getIndentDiff(const QString &previousLine) const;
+ int getIndentDiff(const QString &previousLine,
+ const TextEditor::TabSettings &tabSettings) const;
private:
QStringList m_jumpKeywords;
diff --git a/src/plugins/qmljstools/qmljsindenter.cpp b/src/plugins/qmljstools/qmljsindenter.cpp
index e9b7ec5972d..71abf832b96 100644
--- a/src/plugins/qmljstools/qmljsindenter.cpp
+++ b/src/plugins/qmljstools/qmljsindenter.cpp
@@ -58,13 +58,13 @@ void Indenter::indentBlock(QTextDocument *doc,
{
Q_UNUSED(doc)
- QmlJSTools::CreatorCodeFormatter codeFormatter(tabSettings);
-
- codeFormatter.updateStateUntil(block);
- const int depth = codeFormatter.indentFor(block);
+ const int depth = indentFor(block, tabSettings);
if (depth == -1)
return;
+ QmlJSTools::CreatorCodeFormatter codeFormatter(tabSettings);
+ codeFormatter.updateStateUntil(block);
+
if (isElectricCharacter(typedChar)) {
// only reindent the current line when typing electric characters if the
// indent is the same it would be if the line were empty
@@ -81,3 +81,12 @@ void Indenter::invalidateCache(QTextDocument *doc)
QmlJSTools::CreatorCodeFormatter codeFormatter;
codeFormatter.invalidateCache(doc);
}
+
+
+int Indenter::indentFor(const QTextBlock &block,
+ const TextEditor::TabSettings &tabSettings)
+{
+ QmlJSTools::CreatorCodeFormatter codeFormatter(tabSettings);
+ codeFormatter.updateStateUntil(block);
+ return codeFormatter.indentFor(block);
+}
diff --git a/src/plugins/qmljstools/qmljsindenter.h b/src/plugins/qmljstools/qmljsindenter.h
index 9ded32e53cf..3a7ced9fd0a 100644
--- a/src/plugins/qmljstools/qmljsindenter.h
+++ b/src/plugins/qmljstools/qmljsindenter.h
@@ -37,14 +37,16 @@ class QMLJSTOOLS_EXPORT Indenter : public TextEditor::Indenter
{
public:
Indenter();
- virtual ~Indenter();
-
- virtual bool isElectricCharacter(const QChar &ch) const;
- virtual void indentBlock(QTextDocument *doc,
- const QTextBlock &block,
- const QChar &typedChar,
- const TextEditor::TabSettings &tabSettings);
- virtual void invalidateCache(QTextDocument *doc);
+ ~Indenter() override;
+
+ bool isElectricCharacter(const QChar &ch) const override;
+ void indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ const TextEditor::TabSettings &tabSettings) override;
+ void invalidateCache(QTextDocument *doc) override;
+
+ int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override;
};
} // Internal
diff --git a/src/plugins/texteditor/indenter.cpp b/src/plugins/texteditor/indenter.cpp
index 57573270aba..29e9f8e2a2c 100644
--- a/src/plugins/texteditor/indenter.cpp
+++ b/src/plugins/texteditor/indenter.cpp
@@ -25,6 +25,7 @@
#include "indenter.h"
#include "tabsettings.h"
+#include "textdocumentlayout.h"
#include <QTextDocument>
#include <QTextCursor>
@@ -48,9 +49,11 @@ void Indenter::indentBlock(QTextDocument *doc,
const TabSettings &tabSettings)
{
Q_UNUSED(doc);
- Q_UNUSED(block);
Q_UNUSED(typedChar);
- Q_UNUSED(tabSettings);
+ const int indent = indentFor(block, tabSettings);
+ if (indent < 0)
+ return;
+ tabSettings.indentLine(block, indent);
}
void Indenter::indent(QTextDocument *doc,
@@ -108,3 +111,10 @@ void Indenter::setCodeStylePreferences(ICodeStylePreferences *)
void Indenter::invalidateCache(QTextDocument *)
{
}
+
+int Indenter::indentFor(const QTextBlock &block, const TabSettings &tabSettings)
+{
+ Q_UNUSED(block)
+ Q_UNUSED(tabSettings)
+ return -1;
+}
diff --git a/src/plugins/texteditor/indenter.h b/src/plugins/texteditor/indenter.h
index d41bb020964..8f5093c9dd2 100644
--- a/src/plugins/texteditor/indenter.h
+++ b/src/plugins/texteditor/indenter.h
@@ -68,6 +68,8 @@ public:
virtual void setCodeStylePreferences(ICodeStylePreferences *preferences);
virtual void invalidateCache(QTextDocument *doc);
+
+ virtual int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings);
};
} // namespace TextEditor
diff --git a/src/plugins/texteditor/normalindenter.cpp b/src/plugins/texteditor/normalindenter.cpp
index cc824be0303..d1956d83d89 100644
--- a/src/plugins/texteditor/normalindenter.cpp
+++ b/src/plugins/texteditor/normalindenter.cpp
@@ -28,14 +28,6 @@
#include <QTextDocument>
-using namespace TextEditor;
-
-NormalIndenter::NormalIndenter()
-{}
-
-NormalIndenter::~NormalIndenter()
-{}
-
// Indent a text block based on previous line.
// Simple text paragraph layout:
// aaaa aaaa
@@ -55,31 +47,21 @@ NormalIndenter::~NormalIndenter()
// for additional block being inserted. It might be possible
// to do in 2 steps (indenting/wrapping)}
//
-void NormalIndenter::indentBlock(QTextDocument *doc,
- const QTextBlock &block,
- const QChar &typedChar,
- const TabSettings &tabSettings)
+
+using namespace TextEditor;
+
+int NormalIndenter::indentFor(const QTextBlock &block, const TabSettings &tabSettings)
{
- Q_UNUSED(typedChar)
+ Q_UNUSED(tabSettings);
- // At beginning: Leave as is.
- if (block == doc->begin())
- return;
+ QTextBlock previous = block.previous();
+ if (!previous.isValid())
+ return 0;
- const QTextBlock previous = block.previous();
const QString previousText = previous.text();
// Empty line indicates a start of a new paragraph. Leave as is.
if (previousText.isEmpty() || previousText.trimmed().isEmpty())
- return;
+ return 0;
- // Just use previous line.
- // Skip blank characters when determining the indentation
- int i = 0;
- while (i < previousText.size()) {
- if (!previousText.at(i).isSpace()) {
- tabSettings.indentLine(block, tabSettings.columnAt(previousText, i));
- break;
- }
- ++i;
- }
+ return tabSettings.indentationColumn(previousText);
}
diff --git a/src/plugins/texteditor/normalindenter.h b/src/plugins/texteditor/normalindenter.h
index af5d0c19c59..3cbbb6fd98b 100644
--- a/src/plugins/texteditor/normalindenter.h
+++ b/src/plugins/texteditor/normalindenter.h
@@ -33,13 +33,10 @@ namespace TextEditor {
class TEXTEDITOR_EXPORT NormalIndenter : public Indenter
{
public:
- NormalIndenter();
- virtual ~NormalIndenter();
+ NormalIndenter() {}
+ ~NormalIndenter() override {}
- virtual void indentBlock(QTextDocument *doc,
- const QTextBlock &block,
- const QChar &typedChar,
- const TextEditor::TabSettings &tabSettings);
+ int indentFor(const QTextBlock &block, const TabSettings &tabSettings) override;
};
} // namespace TextEditor
diff --git a/src/plugins/texteditor/tabsettings.cpp b/src/plugins/texteditor/tabsettings.cpp
index c396cf66799..0bf4bc29952 100644
--- a/src/plugins/texteditor/tabsettings.cpp
+++ b/src/plugins/texteditor/tabsettings.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "tabsettings.h"
+#include "texteditorplugin.h"
#include <utils/settingsutils.h>
@@ -42,12 +43,16 @@ static const char paddingModeKey[] = "PaddingMode";
namespace TextEditor {
-TabSettings::TabSettings() :
- m_tabPolicy(SpacesOnlyTabPolicy),
- m_tabSize(8),
- m_indentSize(4),
- m_continuationAlignBehavior(ContinuationAlignWithSpaces)
+TabSettings::TabSettings(TabSettings::TabPolicy tabPolicy,
+ int tabSize,
+ int indentSize,
+ TabSettings::ContinuationAlignBehavior continuationAlignBehavior)
+ : m_tabPolicy(tabPolicy)
+ , m_tabSize(tabSize)
+ , m_indentSize(indentSize)
+ , m_continuationAlignBehavior(continuationAlignBehavior)
{
+
}
void TabSettings::toSettings(const QString &category, QSettings *s) const
@@ -157,7 +162,7 @@ void TabSettings::removeTrailingWhitespace(QTextCursor cursor, QTextBlock &block
}
}
-bool TabSettings::isIndentationClean(const QTextBlock &block) const
+bool TabSettings::isIndentationClean(const QTextBlock &block, const int indent) const
{
int i = 0;
int spaceCount = 0;
@@ -170,10 +175,16 @@ bool TabSettings::isIndentationClean(const QTextBlock &block) const
if (c == QLatin1Char(' ')) {
++spaceCount;
- if (!spacesForTabs && spaceCount == m_tabSize)
+ if (spaceCount == m_tabSize)
+ if (!spacesForTabs)
+ if ((m_continuationAlignBehavior != ContinuationAlignWithSpaces) || (i < indent))
+ return false;
+ if (spaceCount > indent && m_continuationAlignBehavior == NoContinuationAlign)
return false;
} else if (c == QLatin1Char('\t')) {
- if (spacesForTabs || spaceCount != 0)
+ if (spacesForTabs || (spaceCount != 0))
+ return false;
+ if ((m_continuationAlignBehavior != ContinuationAlignWithIndent) && ((i + 1) * m_tabSize > indent))
return false;
}
++i;
@@ -275,23 +286,29 @@ bool TabSettings::guessSpacesForTabs(const QTextBlock &_block) const
return m_tabPolicy != TabsOnlyTabPolicy;
}
-QString TabSettings::indentationString(int startColumn, int targetColumn, const QTextBlock &block) const
+QString TabSettings::indentationString(int startColumn, int targetColumn, int padding,
+ const QTextBlock &block) const
{
targetColumn = qMax(startColumn, targetColumn);
if (guessSpacesForTabs(block))
return QString(targetColumn - startColumn, QLatin1Char(' '));
QString s;
- int alignedStart = startColumn - (startColumn % m_tabSize) + m_tabSize;
+ int alignedStart = startColumn == 0 ? 0 : startColumn - (startColumn % m_tabSize) + m_tabSize;
if (alignedStart > startColumn && alignedStart <= targetColumn) {
s += QLatin1Char('\t');
startColumn = alignedStart;
}
- if (int columns = targetColumn - startColumn) {
- int tabs = columns / m_tabSize;
- s += QString(tabs, QLatin1Char('\t'));
- s += QString(columns - tabs * m_tabSize, QLatin1Char(' '));
+ if (m_continuationAlignBehavior == NoContinuationAlign) {
+ targetColumn -= padding;
+ padding = 0;
+ } else if (m_continuationAlignBehavior == ContinuationAlignWithIndent) {
+ padding = 0;
}
+ const int columns = targetColumn - padding - startColumn;
+ const int tabs = columns / m_tabSize;
+ s += QString(tabs, QLatin1Char('\t'));
+ s += QString(targetColumn - startColumn - tabs * m_tabSize, QLatin1Char(' '));
return s;
}
@@ -313,15 +330,7 @@ void TabSettings::indentLine(QTextBlock block, int newIndent, int padding) const
// if (indentationColumn(text) == newIndent)
// return;
- QString indentString;
-
- if (m_tabPolicy == TabsOnlyTabPolicy) {
- // user likes tabs for spaces and uses tabs for indentation, preserve padding
- indentString = indentationString(0, newIndent - padding, block);
- indentString += QString(padding, QLatin1Char(' '));
- } else {
- indentString = indentationString(0, newIndent, block);
- }
+ const QString indentString = indentationString(0, newIndent, padding, block);
if (oldBlockLength == indentString.length() && text == indentString)
return;
@@ -346,15 +355,11 @@ void TabSettings::reindentLine(QTextBlock block, int delta) const
if (oldIndent == newIndent)
return;
- QString indentString;
- if (m_tabPolicy == TabsOnlyTabPolicy && m_tabSize == m_indentSize) {
- // user likes tabs for spaces and uses tabs for indentation, preserve padding
- int padding = qMin(maximumPadding(text), newIndent);
- indentString = indentationString(0, newIndent - padding, block);
- indentString += QString(padding, QLatin1Char(' '));
- } else {
- indentString = indentationString(0, newIndent, block);
- }
+ int padding = 0;
+ // user likes tabs for spaces and uses tabs for indentation, preserve padding
+ if (m_tabPolicy == TabsOnlyTabPolicy && m_tabSize == m_indentSize)
+ padding = qMin(maximumPadding(text), newIndent);
+ const QString indentString = indentationString(0, newIndent, padding, block);
if (oldBlockLength == indentString.length() && text == indentString)
return;
diff --git a/src/plugins/texteditor/tabsettings.h b/src/plugins/texteditor/tabsettings.h
index a13a2ff87ba..f0b60584b73 100644
--- a/src/plugins/texteditor/tabsettings.h
+++ b/src/plugins/texteditor/tabsettings.h
@@ -55,7 +55,9 @@ public:
ContinuationAlignWithIndent = 2
};
- TabSettings();
+ TabSettings() = default;
+ TabSettings(TabPolicy tabPolicy, int tabSize,
+ int indentSize, ContinuationAlignBehavior continuationAlignBehavior);
void toSettings(const QString &category, QSettings *s) const;
void fromSettings(const QString &category, const QSettings *s);
@@ -68,7 +70,7 @@ public:
int positionAtColumn(const QString &text, int column, int *offset = 0, bool allowOverstep = false) const;
int columnCountForText(const QString &text, int startColumn = 0) const;
int indentedColumn(int column, bool doIndent = true) const;
- QString indentationString(int startColumn, int targetColumn, const QTextBlock &currentBlock = QTextBlock()) const;
+ QString indentationString(int startColumn, int targetColumn, int padding, const QTextBlock &currentBlock = QTextBlock()) const;
QString indentationString(const QString &text) const;
int indentationColumn(const QString &text) const;
static int maximumPadding(const QString &text);
@@ -76,7 +78,7 @@ public:
void indentLine(QTextBlock block, int newIndent, int padding = 0) const;
void reindentLine(QTextBlock block, int delta) const;
- bool isIndentationClean(const QTextBlock &block) const;
+ bool isIndentationClean(const QTextBlock &block, const int indent) const;
bool guessSpacesForTabs(const QTextBlock &block) const;
static int firstNonSpace(const QString &text);
@@ -86,10 +88,10 @@ public:
static int trailingWhitespaces(const QString &text);
static void removeTrailingWhitespace(QTextCursor cursor, QTextBlock &block);
- TabPolicy m_tabPolicy;
- int m_tabSize;
- int m_indentSize;
- ContinuationAlignBehavior m_continuationAlignBehavior;
+ TabPolicy m_tabPolicy = SpacesOnlyTabPolicy;
+ int m_tabSize = 8;
+ int m_indentSize = 4;
+ ContinuationAlignBehavior m_continuationAlignBehavior = ContinuationAlignWithSpaces;
bool equals(const TabSettings &ts) const;
};
@@ -100,5 +102,7 @@ inline bool operator!=(const TabSettings &t1, const TabSettings &t2) { return !t
} // namespace TextEditor
Q_DECLARE_METATYPE(TextEditor::TabSettings)
+Q_DECLARE_METATYPE(TextEditor::TabSettings::TabPolicy)
+Q_DECLARE_METATYPE(TextEditor::TabSettings::ContinuationAlignBehavior)
#endif // TABSETTINGS_H
diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp
index 97a0209e1b7..6df2b7e35c0 100644
--- a/src/plugins/texteditor/textdocument.cpp
+++ b/src/plugins/texteditor/textdocument.cpp
@@ -142,7 +142,7 @@ QTextCursor TextDocumentPrivate::indentOrUnindent(const QTextCursor &textCursor,
indentPosition = ts.firstNonSpace(text);
int targetColumn = ts.indentedColumn(ts.columnAt(text, indentPosition), doIndent);
cursor.setPosition(block.position() + indentPosition);
- cursor.insertText(ts.indentationString(0, targetColumn, block));
+ cursor.insertText(ts.indentationString(0, targetColumn, 0, block));
cursor.setPosition(block.position());
cursor.setPosition(block.position() + indentPosition, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
@@ -159,7 +159,7 @@ QTextCursor TextDocumentPrivate::indentOrUnindent(const QTextCursor &textCursor,
int blockColumn = ts.columnAt(text, text.size());
if (blockColumn < column) {
cursor.setPosition(block.position() + text.size());
- cursor.insertText(ts.indentationString(blockColumn, column, block));
+ cursor.insertText(ts.indentationString(blockColumn, column, 0, block));
text = block.text();
}
@@ -170,7 +170,7 @@ QTextCursor TextDocumentPrivate::indentOrUnindent(const QTextCursor &textCursor,
cursor.setPosition(block.position() + indentPosition);
cursor.setPosition(block.position() + indentPosition - spaces, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
- cursor.insertText(ts.indentationString(startColumn, targetColumn, block));
+ cursor.insertText(ts.indentationString(startColumn, targetColumn, 0, block));
}
// Preserve initial anchor of block selection
if (blockSelection) {
@@ -750,7 +750,8 @@ void TextDocument::cleanWhitespace(QTextCursor &cursor, bool cleanIndentation, b
QString blockText = block.text();
d->m_tabSettings.removeTrailingWhitespace(cursor, block);
- if (cleanIndentation && !d->m_tabSettings.isIndentationClean(block)) {
+ const int indent = d->m_indenter->indentFor(block, d->m_tabSettings);
+ if (cleanIndentation && !d->m_tabSettings.isIndentationClean(block, indent)) {
cursor.setPosition(block.position());
int firstNonSpace = d->m_tabSettings.firstNonSpace(blockText);
if (firstNonSpace == blockText.length()) {
@@ -759,7 +760,7 @@ void TextDocument::cleanWhitespace(QTextCursor &cursor, bool cleanIndentation, b
} else {
int column = d->m_tabSettings.columnAt(blockText, firstNonSpace);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, firstNonSpace);
- QString indentationString = d->m_tabSettings.indentationString(0, column, block);
+ QString indentationString = d->m_tabSettings.indentationString(0, column, column - indent, block);
cursor.insertText(indentationString);
}
}
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index f0653d4b767..a065d191ad9 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -3337,11 +3337,11 @@ void TextEditorWidgetPrivate::setCursorToColumn(QTextCursor &cursor, int column,
cursor.setPosition(cursor.block().position() + pos - 1, QTextCursor::KeepAnchor);
cursor.insertText(ts.indentationString(
ts.columnAt(cursor.block().text(), pos - 1),
- ts.columnAt(cursor.block().text(), pos), cursor.block()));
+ ts.columnAt(cursor.block().text(), pos), 0, cursor.block()));
} else {
// column is behind the last position
cursor.insertText(ts.indentationString(ts.columnAt(cursor.block().text(), pos),
- column, cursor.block()));
+ column, 0, cursor.block()));
}
if (moveMode == QTextCursor::KeepAnchor)
cursor.setPosition(cursorPosition);
@@ -6360,7 +6360,7 @@ void TextEditorWidget::rewrapParagraph()
if (commonPrefix.isEmpty()) {
spacing = d->m_document->tabSettings().indentationString(
- 0, indentLevel, textCursor().block());
+ 0, indentLevel, 0, textCursor().block());
} else {
spacing = commonPrefix;
indentLevel = commonPrefix.length();
diff --git a/src/plugins/texteditor/texteditor_test.cpp b/src/plugins/texteditor/texteditor_test.cpp
index 3d645116ce3..786235d3608 100644
--- a/src/plugins/texteditor/texteditor_test.cpp
+++ b/src/plugins/texteditor/texteditor_test.cpp
@@ -36,6 +36,7 @@
#include "texteditor.h"
#include "texteditorplugin.h"
#include "textdocument.h"
+#include "tabsettings.h"
using namespace TextEditor;
@@ -497,4 +498,133 @@ void Internal::TextEditorPlugin::testBlockSelectionCopy()
Core::EditorManager::closeDocument(editor->document(), false);
}
+QString tabPolicyToString(TabSettings::TabPolicy policy)
+{
+ switch (policy) {
+ case TabSettings::SpacesOnlyTabPolicy:
+ return QLatin1String("spacesOnlyPolicy");
+ case TabSettings::TabsOnlyTabPolicy:
+ return QLatin1String("tabsOnlyPolicy");
+ case TabSettings::MixedTabPolicy:
+ return QLatin1String("mixedIndentPolicy");
+ }
+ return QString();
+}
+
+QString continuationAlignBehaviorToString(TabSettings::ContinuationAlignBehavior behavior)
+{
+ switch (behavior) {
+ case TabSettings::NoContinuationAlign:
+ return QLatin1String("noContinuation");
+ case TabSettings::ContinuationAlignWithSpaces:
+ return QLatin1String("spacesContinuation");
+ case TabSettings::ContinuationAlignWithIndent:
+ return QLatin1String("indentContinuation");
+ }
+ return QString();
+}
+
+struct TabSettingsFlags{
+ TabSettings::TabPolicy policy;
+ TabSettings::ContinuationAlignBehavior behavior;
+};
+
+typedef std::function<bool(TabSettingsFlags)> IsClean;
+void generateTestRows(QLatin1String name, QString text, IsClean isClean)
+{
+ QList<TabSettings::TabPolicy> allPolicys;
+ allPolicys << TabSettings::SpacesOnlyTabPolicy
+ << TabSettings::TabsOnlyTabPolicy
+ << TabSettings::MixedTabPolicy;
+ QList<TabSettings::ContinuationAlignBehavior> allbehavior;
+ allbehavior << TabSettings::NoContinuationAlign
+ << TabSettings::ContinuationAlignWithSpaces
+ << TabSettings::ContinuationAlignWithIndent;
+
+ const QLatin1Char splitter('_');
+ const int indentSize = 3;
+
+ foreach (TabSettings::TabPolicy policy, allPolicys) {
+ foreach (TabSettings::ContinuationAlignBehavior behavior, allbehavior) {
+ const QString tag = tabPolicyToString(policy) + splitter
+ + continuationAlignBehaviorToString(behavior) + splitter
+ + name;
+ QTest::newRow(tag.toLatin1().data())
+ << policy
+ << behavior
+ << text
+ << indentSize
+ << isClean({policy, behavior});
+ }
+ }
+}
+
+void Internal::TextEditorPlugin::testIndentationClean_data()
+{
+ QTest::addColumn<TabSettings::TabPolicy>("policy");
+ QTest::addColumn<TabSettings::ContinuationAlignBehavior>("behavior");
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("indentSize");
+ QTest::addColumn<bool>("clean");
+
+ generateTestRows(QLatin1String("emptyString"), QString::fromLatin1(""),
+ [](TabSettingsFlags) -> bool {
+ return true;
+ });
+
+ generateTestRows(QLatin1String("spaceIndentation"), QString::fromLatin1(" f"),
+ [](TabSettingsFlags flags) -> bool {
+ return flags.policy != TabSettings::TabsOnlyTabPolicy;
+ });
+
+ generateTestRows(QLatin1String("spaceIndentationGuessTabs"), QString::fromLatin1(" f\n\tf"),
+ [](TabSettingsFlags flags) -> bool {
+ return flags.policy == TabSettings::SpacesOnlyTabPolicy;
+ });
+
+ generateTestRows(QLatin1String("tabIndentation"), QString::fromLatin1("\tf"),
+ [](TabSettingsFlags flags) -> bool {
+ return flags.policy == TabSettings::TabsOnlyTabPolicy;
+ });
+
+ generateTestRows(QLatin1String("tabIndentationGuessTabs"), QString::fromLatin1("\tf\n\tf"),
+ [](TabSettingsFlags flags) -> bool {
+ return flags.policy != TabSettings::SpacesOnlyTabPolicy;
+ });
+
+ generateTestRows(QLatin1String("doubleSpaceIndentation"), QString::fromLatin1(" f"),
+ [](TabSettingsFlags flags) -> bool {
+ return flags.policy != TabSettings::TabsOnlyTabPolicy
+ && flags.behavior != TabSettings::NoContinuationAlign;
+ });
+
+ generateTestRows(QLatin1String("doubleTabIndentation"), QString::fromLatin1("\t\tf"),
+ [](TabSettingsFlags flags) -> bool {
+ return flags.policy == TabSettings::TabsOnlyTabPolicy
+ && flags.behavior == TabSettings::ContinuationAlignWithIndent;
+ });
+
+ generateTestRows(QLatin1String("tabSpaceIndentation"), QString::fromLatin1("\t f"),
+ [](TabSettingsFlags flags) -> bool {
+ return flags.policy == TabSettings::TabsOnlyTabPolicy
+ && flags.behavior == TabSettings::ContinuationAlignWithSpaces;
+ });
+}
+
+void Internal::TextEditorPlugin::testIndentationClean()
+{
+ // fetch test data
+ QFETCH(TabSettings::TabPolicy, policy);
+ QFETCH(TabSettings::ContinuationAlignBehavior, behavior);
+ QFETCH(QString, text);
+ QFETCH(int, indentSize);
+ QFETCH(bool, clean);
+
+ const TabSettings settings(policy, indentSize, indentSize, behavior);
+ const QTextDocument doc(text);
+ const QTextBlock block = doc.firstBlock();
+
+ QCOMPARE(settings.isIndentationClean(block, indentSize), clean);
+}
+
#endif // ifdef WITH_TESTS
diff --git a/src/plugins/texteditor/texteditorplugin.h b/src/plugins/texteditor/texteditorplugin.h
index b66feb99db7..f8486caa67b 100644
--- a/src/plugins/texteditor/texteditorplugin.h
+++ b/src/plugins/texteditor/texteditorplugin.h
@@ -79,6 +79,9 @@ private slots:
void testBlockSelectionRemove();
void testBlockSelectionCopy_data();
void testBlockSelectionCopy();
+
+ void testIndentationClean_data();
+ void testIndentationClean();
#endif
};