C++: Add settings dialog for pointer declaration formatting

The dialog is at Tools > Options > C++ > Code Style > Edit... > Pointers
and References.

Currently the settings are referenced when applying the following
QuickFixes:
 - Adapting function signature in declaration/definition
   (FunctionDeclDefLink)
 - Inserting declaration from definition (InsertDeclOperation)
 - Inserting definition from declaration (InsertDefOperation)
 - Extracting a function (ExtractFunctionOperation)
 - Add Local Declaration (AddLocalDeclarationOp::Operation)

In these cases the code style of the current project is used. If there
is no current project open, the current global code style is used.

Task-number: QTCREATORBUG-6169

Change-Id: I3e4e502b3103f7f754ac9b39594ad461d89d9304
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
Nikolai Kosjar
2013-01-15 14:26:24 +01:00
parent 138066792e
commit 8fe25d0a4a
7 changed files with 309 additions and 31 deletions

View File

@@ -29,6 +29,19 @@
#include "cppcodestylesettings.h"
#include <cpptools/cppcodestylepreferences.h>
#include <cpptools/cppcodestylesettings.h>
#include <cpptools/cpptoolsconstants.h>
#include <cpptools/cpptoolssettings.h>
#include <projectexplorer/editorconfiguration.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <cppcodestylepreferencesfactory.h>
#include <utils/qtcassert.h>
#include <utils/settingsutils.h>
static const char groupPostfix[] = "IndentSettings";
@@ -46,6 +59,10 @@ static const char indentSwitchLabelsKey[] = "IndentSwitchLabels";
static const char indentStatementsRelativeToSwitchLabelsKey[] = "IndentStatementsRelativeToSwitchLabels";
static const char indentBlocksRelativeToSwitchLabelsKey[] = "IndentBlocksRelativeToSwitchLabels";
static const char indentControlFlowRelativeToSwitchLabelsKey[] = "IndentControlFlowRelativeToSwitchLabels";
static const char bindStarToIdentifierKey[] = "BindStarToIdentifier";
static const char bindStarToTypeNameKey[] = "BindStarToTypeName";
static const char bindStarToLeftSpecifierKey[] = "BindStarToLeftSpecifier";
static const char bindStarToRightSpecifierKey[] = "BindStarToRightSpecifier";
static const char extraPaddingForConditionsIfConfusingAlignKey[] = "ExtraPaddingForConditionsIfConfusingAlign";
static const char alignAssignmentsKey[] = "AlignAssignments";
@@ -68,6 +85,10 @@ CppCodeStyleSettings::CppCodeStyleSettings() :
, indentStatementsRelativeToSwitchLabels(true)
, indentBlocksRelativeToSwitchLabels(false)
, indentControlFlowRelativeToSwitchLabels(true)
, bindStarToIdentifier(true)
, bindStarToTypeName(false)
, bindStarToLeftSpecifier(false)
, bindStarToRightSpecifier(false)
, extraPaddingForConditionsIfConfusingAlign(true)
, alignAssignments(false)
{
@@ -100,6 +121,10 @@ void CppCodeStyleSettings::toMap(const QString &prefix, QVariantMap *map) const
map->insert(prefix + QLatin1String(indentStatementsRelativeToSwitchLabelsKey), indentStatementsRelativeToSwitchLabels);
map->insert(prefix + QLatin1String(indentBlocksRelativeToSwitchLabelsKey), indentBlocksRelativeToSwitchLabels);
map->insert(prefix + QLatin1String(indentControlFlowRelativeToSwitchLabelsKey), indentControlFlowRelativeToSwitchLabels);
map->insert(prefix + QLatin1String(bindStarToIdentifierKey), bindStarToIdentifier);
map->insert(prefix + QLatin1String(bindStarToTypeNameKey), bindStarToTypeName);
map->insert(prefix + QLatin1String(bindStarToLeftSpecifierKey), bindStarToLeftSpecifier);
map->insert(prefix + QLatin1String(bindStarToRightSpecifierKey), bindStarToRightSpecifier);
map->insert(prefix + QLatin1String(extraPaddingForConditionsIfConfusingAlignKey), extraPaddingForConditionsIfConfusingAlign);
map->insert(prefix + QLatin1String(alignAssignmentsKey), alignAssignments);
}
@@ -134,6 +159,14 @@ void CppCodeStyleSettings::fromMap(const QString &prefix, const QVariantMap &map
indentBlocksRelativeToSwitchLabels).toBool();
indentControlFlowRelativeToSwitchLabels = map.value(prefix + QLatin1String(indentControlFlowRelativeToSwitchLabelsKey),
indentControlFlowRelativeToSwitchLabels).toBool();
bindStarToIdentifier = map.value(prefix + QLatin1String(bindStarToIdentifierKey),
bindStarToIdentifier).toBool();
bindStarToTypeName = map.value(prefix + QLatin1String(bindStarToTypeNameKey),
bindStarToTypeName).toBool();
bindStarToLeftSpecifier = map.value(prefix + QLatin1String(bindStarToLeftSpecifierKey),
bindStarToLeftSpecifier).toBool();
bindStarToRightSpecifier = map.value(prefix + QLatin1String(bindStarToRightSpecifierKey),
bindStarToRightSpecifier).toBool();
extraPaddingForConditionsIfConfusingAlign = map.value(prefix + QLatin1String(extraPaddingForConditionsIfConfusingAlignKey),
extraPaddingForConditionsIfConfusingAlign).toBool();
alignAssignments = map.value(prefix + QLatin1String(alignAssignmentsKey),
@@ -156,7 +189,61 @@ bool CppCodeStyleSettings::equals(const CppCodeStyleSettings &rhs) const
&& indentStatementsRelativeToSwitchLabels == rhs.indentStatementsRelativeToSwitchLabels
&& indentBlocksRelativeToSwitchLabels == rhs.indentBlocksRelativeToSwitchLabels
&& indentControlFlowRelativeToSwitchLabels == rhs.indentControlFlowRelativeToSwitchLabels
&& bindStarToIdentifier == rhs.bindStarToIdentifier
&& bindStarToTypeName == rhs.bindStarToTypeName
&& bindStarToLeftSpecifier == rhs.bindStarToLeftSpecifier
&& bindStarToRightSpecifier == rhs.bindStarToRightSpecifier
&& extraPaddingForConditionsIfConfusingAlign == rhs.extraPaddingForConditionsIfConfusingAlign
&& alignAssignments == rhs.alignAssignments;
&& alignAssignments == rhs.alignAssignments;
}
static void configureOverviewWithCodeStyleSettings(CPlusPlus::Overview &overview,
const CppCodeStyleSettings &settings)
{
overview.starBindFlags = CPlusPlus::Overview::StarBindFlags(0);
if (settings.bindStarToIdentifier)
overview.starBindFlags |= CPlusPlus::Overview::BindToIdentifier;
if (settings.bindStarToTypeName)
overview.starBindFlags |= CPlusPlus::Overview::BindToTypeName;
if (settings.bindStarToLeftSpecifier)
overview.starBindFlags |= CPlusPlus::Overview::BindToLeftSpecifier;
if (settings.bindStarToRightSpecifier)
overview.starBindFlags |= CPlusPlus::Overview::BindToRightSpecifier;
}
CPlusPlus::Overview CppCodeStyleSettings::currentProjectCodeStyleOverview()
{
ProjectExplorer::Project *project = ProjectExplorer::ProjectExplorerPlugin::currentProject();
if (! project)
return currentGlobalCodeStyleOverview();
ProjectExplorer::EditorConfiguration *editorConfiguration = project->editorConfiguration();
QTC_ASSERT(editorConfiguration, return currentGlobalCodeStyleOverview());
TextEditor::ICodeStylePreferences *codeStylePreferences
= editorConfiguration->codeStyle(Constants::CPP_SETTINGS_ID);
QTC_ASSERT(codeStylePreferences, return currentGlobalCodeStyleOverview());
CppCodeStylePreferences *cppCodeStylePreferences
= dynamic_cast<CppCodeStylePreferences *>(codeStylePreferences);
QTC_ASSERT(cppCodeStylePreferences, return currentGlobalCodeStyleOverview());
CppCodeStyleSettings settings = cppCodeStylePreferences->currentCodeStyleSettings();
CPlusPlus::Overview overview;
configureOverviewWithCodeStyleSettings(overview, settings);
return overview;
}
CPlusPlus::Overview CppCodeStyleSettings::currentGlobalCodeStyleOverview()
{
CPlusPlus::Overview overview;
CppCodeStylePreferences *cppCodeStylePreferences = CppToolsSettings::instance()->cppCodeStyle();
QTC_ASSERT(cppCodeStylePreferences, return overview);
CppCodeStyleSettings settings = cppCodeStylePreferences->currentCodeStyleSettings();
configureOverviewWithCodeStyleSettings(overview, settings);
return overview;
}

View File

@@ -32,6 +32,8 @@
#include "cpptools_global.h"
#include <cplusplus/Overview.h>
#include <QMetaType>
#include <QVariant>
@@ -61,6 +63,12 @@ public:
bool indentBlocksRelativeToSwitchLabels;
bool indentControlFlowRelativeToSwitchLabels;
// Formatting of pointer and reference declarations, see Overview::StarBindFlag.
bool bindStarToIdentifier;
bool bindStarToTypeName;
bool bindStarToLeftSpecifier;
bool bindStarToRightSpecifier;
// false: if (a &&
// b)
// c;
@@ -87,6 +95,21 @@ public:
bool equals(const CppCodeStyleSettings &rhs) const;
bool operator==(const CppCodeStyleSettings &s) const { return equals(s); }
bool operator!=(const CppCodeStyleSettings &s) const { return !equals(s); }
/*! Returns an Overview configured by the current project's code style.
If no current project is available or an error occurs when getting the
current project's code style, the current global code style settings
are applied.
*/
static CPlusPlus::Overview currentProjectCodeStyleOverview();
/*! Returns an Overview configured by the current global code style.
If there occurred an error getting the current global code style, a
default constructed Overview is returned.
*/
static CPlusPlus::Overview currentGlobalCodeStyleOverview();
};
} // namespace CppTools

View File

@@ -27,21 +27,27 @@
**
****************************************************************************/
#include "cppcodestylesettingspage.h"
#include "cppcodestylepreferences.h"
#include "ui_cppcodestylesettingspage.h"
#include "cppcodestylesettingspage.h"
#include "cpppointerdeclarationformatter.h"
#include "cppqtstyleindenter.h"
#include "cpptoolsconstants.h"
#include "cpptoolssettings.h"
#include "cppqtstyleindenter.h"
#include <texteditor/snippets/isnippetprovider.h>
#include <texteditor/fontsettings.h>
#include <texteditor/displaysettings.h>
#include <texteditor/texteditorsettings.h>
#include <texteditor/tabsettings.h>
#include <texteditor/codestyleeditor.h>
#include <extensionsystem/pluginmanager.h>
#include <cppeditor/cppeditorconstants.h>
#include "ui_cppcodestylesettingspage.h"
#include <Overview.h>
#include <pp.h>
#include <coreplugin/icore.h>
#include <cppeditor/cppeditorconstants.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/codestyleeditor.h>
#include <texteditor/displaysettings.h>
#include <texteditor/fontsettings.h>
#include <texteditor/snippets/isnippetprovider.h>
#include <texteditor/tabsettings.h>
#include <texteditor/texteditorsettings.h>
#include <QTextBlock>
#include <QTextStream>
@@ -194,6 +200,19 @@ static const char *defaultCodeStyleSnippets[] = {
" myInstance.longMemberName += bar +\n"
" foo;\n"
"}\n"
,
"int *foo(const Bar &b1, Bar &&b2, int*, int *&rpi)\n"
"{\n"
" int*pi = 0;\n"
" int*const*const cpcpi = &pi;\n"
" int*const*pcpi = &pi;\n"
" int**const cppi = &pi;\n"
"\n"
" void (*foo)(char *s) = 0;\n"
" int (*bar)[] = 0;\n"
"\n"
" return pi;\n"
"}\n"
};
using namespace TextEditor;
@@ -202,6 +221,44 @@ namespace CppTools {
namespace Internal {
static void applyRefactorings(QTextDocument *textDocument, TextEditor::BaseTextEditorWidget *editor,
const CppCodeStyleSettings &settings)
{
// Preprocess source
Environment env;
Preprocessor preprocess(0, &env);
const QByteArray preprocessedSource
= preprocess.run(QLatin1String("<no-file>"), textDocument->toPlainText());
Document::Ptr cppDocument = Document::create(QLatin1String("<no-file>"));
cppDocument->setUtf8Source(preprocessedSource);
cppDocument->parse(Document::ParseTranlationUnit);
cppDocument->check();
CppRefactoringFilePtr cppRefactoringFile = CppRefactoringChanges::file(editor, cppDocument);
// Run the formatter
Overview overview;
overview.showReturnTypes = true;
overview.starBindFlags = Overview::StarBindFlags(0);
if (settings.bindStarToIdentifier)
overview.starBindFlags |= Overview::BindToIdentifier;
if (settings.bindStarToTypeName)
overview.starBindFlags |= Overview::BindToTypeName;
if (settings.bindStarToLeftSpecifier)
overview.starBindFlags |= Overview::BindToLeftSpecifier;
if (settings.bindStarToRightSpecifier)
overview.starBindFlags |= Overview::BindToRightSpecifier;
PointerDeclarationFormatter formatter(cppRefactoringFile, overview);
Utils::ChangeSet change = formatter.format(cppDocument->translationUnit()->ast());
// Apply change
QTextCursor cursor(textDocument);
change.apply(&cursor);
}
// ------------------ CppCodeStyleSettingsWidget
CppCodeStylePreferencesWidget::CppCodeStylePreferencesWidget(QWidget *parent)
@@ -215,7 +272,7 @@ CppCodeStylePreferencesWidget::CppCodeStylePreferencesWidget(QWidget *parent)
m_previews << m_ui->previewTextEditGeneral << m_ui->previewTextEditContent
<< m_ui->previewTextEditBraces << m_ui->previewTextEditSwitch
<< m_ui->previewTextEditPadding;
<< m_ui->previewTextEditPadding << m_ui->previewTextEditPointerReferences;
for (int i = 0; i < m_previews.size(); ++i)
m_previews[i]->setPlainText(QLatin1String(defaultCodeStyleSnippets[i]));
@@ -260,6 +317,14 @@ CppCodeStylePreferencesWidget::CppCodeStylePreferencesWidget(QWidget *parent)
this, SLOT(slotCodeStyleSettingsChanged()));
connect(m_ui->alignAssignments, SIGNAL(toggled(bool)),
this, SLOT(slotCodeStyleSettingsChanged()));
connect(m_ui->bindStarToIdentifier, SIGNAL(toggled(bool)),
this, SLOT(slotCodeStyleSettingsChanged()));
connect(m_ui->bindStarToTypeName, SIGNAL(toggled(bool)),
this, SLOT(slotCodeStyleSettingsChanged()));
connect(m_ui->bindStarToLeftSpecifier, SIGNAL(toggled(bool)),
this, SLOT(slotCodeStyleSettingsChanged()));
connect(m_ui->bindStarToRightSpecifier, SIGNAL(toggled(bool)),
this, SLOT(slotCodeStyleSettingsChanged()));
m_ui->categoryTab->setCurrentIndex(0);
@@ -308,6 +373,10 @@ CppCodeStyleSettings CppCodeStylePreferencesWidget::cppCodeStyleSettings() const
set.indentStatementsRelativeToSwitchLabels = m_ui->indentCaseStatements->isChecked();
set.indentBlocksRelativeToSwitchLabels = m_ui->indentCaseBlocks->isChecked();
set.indentControlFlowRelativeToSwitchLabels = m_ui->indentCaseBreak->isChecked();
set.bindStarToIdentifier = m_ui->bindStarToIdentifier->isChecked();
set.bindStarToTypeName = m_ui->bindStarToTypeName->isChecked();
set.bindStarToLeftSpecifier = m_ui->bindStarToLeftSpecifier->isChecked();
set.bindStarToRightSpecifier = m_ui->bindStarToRightSpecifier->isChecked();
set.extraPaddingForConditionsIfConfusingAlign = m_ui->extraPaddingConditions->isChecked();
set.alignAssignments = m_ui->alignAssignments->isChecked();
@@ -337,6 +406,10 @@ void CppCodeStylePreferencesWidget::setCodeStyleSettings(const CppCodeStyleSetti
m_ui->indentCaseStatements->setChecked(s.indentStatementsRelativeToSwitchLabels);
m_ui->indentCaseBlocks->setChecked(s.indentBlocksRelativeToSwitchLabels);
m_ui->indentCaseBreak->setChecked(s.indentControlFlowRelativeToSwitchLabels);
m_ui->bindStarToIdentifier->setChecked(s.bindStarToIdentifier);
m_ui->bindStarToTypeName->setChecked(s.bindStarToTypeName);
m_ui->bindStarToLeftSpecifier->setChecked(s.bindStarToLeftSpecifier);
m_ui->bindStarToRightSpecifier->setChecked(s.bindStarToRightSpecifier);
m_ui->extraPaddingConditions->setChecked(s.extraPaddingForConditionsIfConfusingAlign);
m_ui->alignAssignments->setChecked(s.alignAssignments);
m_blockUpdates = wasBlocked;
@@ -352,6 +425,7 @@ void CppCodeStylePreferencesWidget::slotCurrentPreferencesChanged(TextEditor::IC
m_ui->bracesGroupBox->setEnabled(enable);
m_ui->switchGroupBox->setEnabled(enable);
m_ui->alignmentGroupBox->setEnabled(enable);
m_ui->pointerReferencesGroupBox->setEnabled(enable);
if (preview)
updatePreview();
}
@@ -376,10 +450,15 @@ QString CppCodeStylePreferencesWidget::searchKeywords() const
<< sep << m_ui->indentCaseStatements->text()
<< sep << m_ui->indentCaseBlocks->text()
<< sep << m_ui->indentCaseBreak->text()
<< sep << m_ui->bindStarToIdentifier->text()
<< sep << m_ui->bindStarToTypeName->text()
<< sep << m_ui->bindStarToLeftSpecifier->text()
<< sep << m_ui->bindStarToRightSpecifier->text()
<< sep << m_ui->contentGroupBox->title()
<< sep << m_ui->bracesGroupBox->title()
<< sep << m_ui->switchGroupBox->title()
<< sep << m_ui->alignmentGroupBox->title()
<< sep << m_ui->pointerReferencesGroupBox->title()
<< sep << m_ui->extraPaddingConditions->text()
<< sep << m_ui->alignAssignments->text()
;
@@ -440,6 +519,7 @@ void CppCodeStylePreferencesWidget::updatePreview()
block = block.next();
}
applyRefactorings(doc, preview, ccss);
tc.endEditBlock();
}
}

View File

@@ -17,7 +17,7 @@
<item>
<widget class="QTabWidget" name="categoryTab">
<property name="currentIndex">
<number>0</number>
<number>5</number>
</property>
<widget class="QWidget" name="generalTab">
<attribute name="title">
@@ -404,6 +404,86 @@ if they would align to the next line</string>
</item>
</layout>
</widget>
<widget class="QWidget" name="typesTab">
<attribute name="title">
<string>Pointers and References</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QGroupBox" name="pointerReferencesGroupBox">
<property name="title">
<string>Bind '*' and '&amp;&amp;' in types/declarations to</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QCheckBox" name="bindStarToIdentifier">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;This does not apply to the star and reference symbol in pointer/reference to functions and arrays, e.g.:
&lt;pre&gt; int (&amp;rf)() = ...;
int (*pf)() = ...;
int (&amp;ra)[2] = ...;
int (*pa)[2] = ...;
&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Identifier</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="bindStarToTypeName">
<property name="text">
<string>Type name</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="bindStarToLeftSpecifier">
<property name="text">
<string>Left const/volatile</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="bindStarToRightSpecifier">
<property name="toolTip">
<string>This does not apply to references.</string>
</property>
<property name="text">
<string>Right const/volatile</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="TextEditor::SnippetEditorWidget" name="previewTextEditPointerReferences">
<property name="plainText">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>