forked from qt-creator/qt-creator
CppEditor: Make header guard naming user-configurable
Fixes: QTCREATORBUG-25117 Change-Id: I732e9a8f146b4d6a346492141ec364a99f167b94 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -29,23 +29,6 @@ QTCREATOR_UTILS_EXPORT QString fileNameToCppIdentifier(const QString &s)
|
||||
return rc;
|
||||
}
|
||||
|
||||
QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file)
|
||||
{
|
||||
return headerGuard(file, QStringList());
|
||||
}
|
||||
|
||||
QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file, const QStringList &namespaceList)
|
||||
{
|
||||
const QChar underscore = QLatin1Char('_');
|
||||
QString rc;
|
||||
for (int i = 0; i < namespaceList.count(); i++)
|
||||
rc += namespaceList.at(i).toUpper() + underscore;
|
||||
|
||||
const QFileInfo fi(file);
|
||||
rc += fileNameToCppIdentifier(fi.fileName()).toUpper();
|
||||
return rc;
|
||||
}
|
||||
|
||||
QTCREATOR_UTILS_EXPORT
|
||||
void writeIncludeFileDirective(const QString &file, bool globalInclude,
|
||||
QTextStream &str)
|
||||
|
@@ -17,9 +17,6 @@ namespace Utils {
|
||||
// or replacing them by an underscore).
|
||||
QTCREATOR_UTILS_EXPORT QString fileNameToCppIdentifier(const QString &s);
|
||||
|
||||
QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file);
|
||||
QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file, const QStringList &namespaceList);
|
||||
|
||||
QTCREATOR_UTILS_EXPORT
|
||||
void writeIncludeFileDirective(const QString &file,
|
||||
bool globalInclude,
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <cppeditor/clangdiagnosticconfigsmodel.h>
|
||||
#include <cppeditor/compileroptionsbuilder.h>
|
||||
#include <cppeditor/cppcodemodelsettings.h>
|
||||
#include <cppeditor/cppprojectfile.h>
|
||||
#include <cppeditor/cpptoolsreuse.h>
|
||||
|
@@ -227,7 +227,7 @@ void CppEditorPlugin::initialize()
|
||||
void CppEditorPlugin::extensionsInitialized()
|
||||
{
|
||||
setupCppQuickFixProjectPanel();
|
||||
setupCppFileSettings();
|
||||
setupCppFileSettings(*this);
|
||||
setupCppCodeModelProjectSettingsPanel();
|
||||
|
||||
if (CppModelManager::isClangCodeModelActive()) {
|
||||
|
@@ -6,15 +6,19 @@
|
||||
#include "cppeditortr.h"
|
||||
#include "cppheadersource.h"
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectpanelfactory.h>
|
||||
|
||||
#include <utils/aspects.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/layoutbuilder.h>
|
||||
#include <utils/macroexpander.h>
|
||||
#include <utils/mimeconstants.h>
|
||||
#include <utils/mimeutils.h>
|
||||
#include <utils/pathchooser.h>
|
||||
@@ -29,10 +33,30 @@
|
||||
#include <QTextStream>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
#include <QtTest>
|
||||
#endif
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace CppEditor::Internal {
|
||||
namespace {
|
||||
class HeaderGuardExpander : public MacroExpander
|
||||
{
|
||||
public:
|
||||
HeaderGuardExpander(const FilePath &filePath) : m_filePath(filePath)
|
||||
{
|
||||
setDisplayName(Tr::tr("Header file variables"));
|
||||
registerFileVariables("Header", Tr::tr("Header file"), [this] {
|
||||
return m_filePath;
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
const FilePath m_filePath;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
const char projectSettingsKeyC[] = "CppEditorFileNames";
|
||||
const char useGlobalKeyC[] = "UseGlobal";
|
||||
@@ -44,6 +68,7 @@ const char headerSearchPathsKeyC[] = "HeaderSearchPaths";
|
||||
const char sourceSearchPathsKeyC[] = "SourceSearchPaths";
|
||||
const char headerPragmaOnceC[] = "HeaderPragmaOnce";
|
||||
const char licenseTemplatePathKeyC[] = "LicenseTemplate";
|
||||
const char headerGuardTemplateKeyC[] = "HeaderGuardTemplate";
|
||||
|
||||
const char *licenseTemplateTemplate = QT_TRANSLATE_NOOP("QtC::CppEditor",
|
||||
"/**************************************************************************\n"
|
||||
@@ -67,6 +92,7 @@ void CppFileSettings::toSettings(QtcSettings *s) const
|
||||
s->setValueWithDefault(headerPragmaOnceC, headerPragmaOnce, def.headerPragmaOnce);
|
||||
s->setValueWithDefault(licenseTemplatePathKeyC, licenseTemplatePath.toSettings(),
|
||||
def.licenseTemplatePath.toSettings());
|
||||
s->setValueWithDefault(headerGuardTemplateKeyC, headerGuardTemplate, def.headerGuardTemplate);
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
@@ -84,6 +110,7 @@ void CppFileSettings::fromSettings(QtcSettings *s)
|
||||
headerPragmaOnce = s->value(headerPragmaOnceC, def.headerPragmaOnce).toBool();
|
||||
licenseTemplatePath = FilePath::fromSettings(s->value(licenseTemplatePathKeyC,
|
||||
def.licenseTemplatePath.toSettings()));
|
||||
headerGuardTemplate = s->value(headerGuardTemplateKeyC, def.headerGuardTemplate).toString();
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
@@ -124,6 +151,7 @@ bool CppFileSettings::equals(const CppFileSettings &rhs) const
|
||||
&& sourceSuffix == rhs.sourceSuffix
|
||||
&& headerSearchPaths == rhs.headerSearchPaths
|
||||
&& sourceSearchPaths == rhs.sourceSearchPaths
|
||||
&& headerGuardTemplate == rhs.headerGuardTemplate
|
||||
&& licenseTemplatePath == rhs.licenseTemplatePath;
|
||||
}
|
||||
|
||||
@@ -237,6 +265,11 @@ QString CppFileSettings::licenseTemplate() const
|
||||
return license;
|
||||
}
|
||||
|
||||
QString CppFileSettings::headerGuard(const Utils::FilePath &headerFilePath) const
|
||||
{
|
||||
return HeaderGuardExpander(headerFilePath).expand(headerGuardTemplate);
|
||||
}
|
||||
|
||||
// ------------------ CppFileSettingsWidget
|
||||
|
||||
class CppFileSettingsWidget final : public Core::IOptionsPageWidget
|
||||
@@ -269,6 +302,8 @@ private:
|
||||
QLineEdit *m_sourcePrefixesEdit = nullptr;
|
||||
QCheckBox *m_lowerCaseFileNamesCheckBox = nullptr;
|
||||
PathChooser *m_licenseTemplatePathChooser = nullptr;
|
||||
StringAspect m_headerGuardAspect;
|
||||
HeaderGuardExpander m_headerGuardExpander{{}};
|
||||
};
|
||||
|
||||
CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings)
|
||||
@@ -276,7 +311,7 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings)
|
||||
, m_headerSuffixComboBox(new QComboBox)
|
||||
, m_headerSearchPathsEdit(new QLineEdit)
|
||||
, m_headerPrefixesEdit(new QLineEdit)
|
||||
, m_headerPragmaOnceCheckBox(new QCheckBox(Tr::tr("Use \"#pragma once\" instead of \"#ifndef\" guards")))
|
||||
, m_headerPragmaOnceCheckBox(new QCheckBox(Tr::tr("Use \"#pragma once\" instead")))
|
||||
, m_sourceSuffixComboBox(new QComboBox)
|
||||
, m_sourceSearchPathsEdit(new QLineEdit)
|
||||
, m_sourcePrefixesEdit(new QLineEdit)
|
||||
@@ -301,6 +336,8 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings)
|
||||
m_sourcePrefixesEdit->setToolTip(Tr::tr("Comma-separated list of source prefixes.\n"
|
||||
"\n"
|
||||
"These prefixes are used in addition to current file name on Switch Header/Source."));
|
||||
m_headerGuardAspect.setDisplayStyle(Utils::StringAspect::LineEditDisplay);
|
||||
m_headerGuardAspect.setMacroExpander(&m_headerGuardExpander);
|
||||
|
||||
using namespace Layouting;
|
||||
|
||||
@@ -311,8 +348,8 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings)
|
||||
Tr::tr("&Suffix:"), m_headerSuffixComboBox, st, br,
|
||||
Tr::tr("S&earch paths:"), m_headerSearchPathsEdit, br,
|
||||
Tr::tr("&Prefixes:"), m_headerPrefixesEdit, br,
|
||||
Tr::tr("Include guards"), m_headerPragmaOnceCheckBox
|
||||
}
|
||||
Tr::tr("Include guard template:"), m_headerPragmaOnceCheckBox, m_headerGuardAspect
|
||||
},
|
||||
},
|
||||
Group {
|
||||
title(Tr::tr("Sources")),
|
||||
@@ -361,12 +398,21 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings)
|
||||
this, &CppFileSettingsWidget::userChange);
|
||||
connect(m_sourcePrefixesEdit, &QLineEdit::textEdited,
|
||||
this, &CppFileSettingsWidget::userChange);
|
||||
connect(m_headerPragmaOnceCheckBox, &QCheckBox::stateChanged,
|
||||
this, &CppFileSettingsWidget::userChange);
|
||||
connect(m_lowerCaseFileNamesCheckBox, &QCheckBox::stateChanged,
|
||||
this, &CppFileSettingsWidget::userChange);
|
||||
connect(m_licenseTemplatePathChooser, &PathChooser::textChanged,
|
||||
this, &CppFileSettingsWidget::userChange);
|
||||
const auto updateHeaderGuardAspectState = [this] {
|
||||
m_headerGuardAspect.setEnabled(!m_headerPragmaOnceCheckBox->isChecked());
|
||||
};
|
||||
connect(m_headerPragmaOnceCheckBox, &QCheckBox::stateChanged,
|
||||
this, [this, updateHeaderGuardAspectState] {
|
||||
updateHeaderGuardAspectState();
|
||||
emit userChange();
|
||||
});
|
||||
connect(&m_headerGuardAspect, &StringAspect::changed,
|
||||
this, &CppFileSettingsWidget::userChange);
|
||||
updateHeaderGuardAspectState();
|
||||
}
|
||||
|
||||
FilePath CppFileSettingsWidget::licenseTemplatePath() const
|
||||
@@ -417,6 +463,7 @@ void CppFileSettingsWidget::setSettings(const CppFileSettings &s)
|
||||
m_headerSearchPathsEdit->setText(s.headerSearchPaths.join(comma));
|
||||
m_sourceSearchPathsEdit->setText(s.sourceSearchPaths.join(comma));
|
||||
setLicenseTemplatePath(s.licenseTemplatePath);
|
||||
m_headerGuardAspect.setValue(s.headerGuardTemplate);
|
||||
}
|
||||
|
||||
CppFileSettings CppFileSettingsWidget::currentSettings() const
|
||||
@@ -431,6 +478,7 @@ CppFileSettings CppFileSettingsWidget::currentSettings() const
|
||||
rc.headerSearchPaths = trimmedPaths(m_headerSearchPathsEdit->text());
|
||||
rc.sourceSearchPaths = trimmedPaths(m_sourceSearchPathsEdit->text());
|
||||
rc.licenseTemplatePath = licenseTemplatePath();
|
||||
rc.headerGuardTemplate = m_headerGuardAspect.value();
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -536,6 +584,8 @@ void CppFileSettingsForProject::loadSettings()
|
||||
m_customSettings.lowerCaseFiles).toBool();
|
||||
m_customSettings.headerPragmaOnce = data.value(headerPragmaOnceC,
|
||||
m_customSettings.headerPragmaOnce).toBool();
|
||||
m_customSettings.headerGuardTemplate
|
||||
= data.value(headerGuardTemplateKeyC, m_customSettings.headerGuardTemplate).toString();
|
||||
m_customSettings.licenseTemplatePath
|
||||
= FilePath::fromSettings(data.value(licenseTemplatePathKeyC,
|
||||
m_customSettings.licenseTemplatePath.toSettings()));
|
||||
@@ -560,6 +610,7 @@ void CppFileSettingsForProject::saveSettings()
|
||||
data.insert(sourceSearchPathsKeyC, m_customSettings.sourceSearchPaths);
|
||||
data.insert(Constants::LOWERCASE_CPPFILES_KEY, m_customSettings.lowerCaseFiles);
|
||||
data.insert(headerPragmaOnceC, m_customSettings.headerPragmaOnce);
|
||||
data.insert(headerGuardTemplateKeyC, m_customSettings.headerGuardTemplate);
|
||||
data.insert(licenseTemplatePathKeyC, m_customSettings.licenseTemplatePath.toSettings());
|
||||
m_project->setNamedSettings(projectSettingsKeyC, data);
|
||||
}
|
||||
@@ -631,16 +682,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void setupCppFileSettings()
|
||||
{
|
||||
static CppFileSettingsProjectPanelFactory theCppFileSettingsProjectPanelFactory;
|
||||
|
||||
static CppFileSettingsPage theCppFileSettingsPage;
|
||||
|
||||
globalCppFileSettings().fromSettings(Core::ICore::settings());
|
||||
globalCppFileSettings().addMimeInitializer();
|
||||
}
|
||||
|
||||
CppFileSettings &globalCppFileSettings()
|
||||
{
|
||||
// This is the global instance. There could be more.
|
||||
@@ -653,6 +694,59 @@ CppFileSettings cppFileSettingsForProject(ProjectExplorer::Project *project)
|
||||
return CppFileSettingsForProject(project).settings();
|
||||
}
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
namespace {
|
||||
class CppFileSettingsTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void testHeaderGuard_data()
|
||||
{
|
||||
QTest::addColumn<QString>("guardTemplate");
|
||||
QTest::addColumn<QString>("headerFile");
|
||||
QTest::addColumn<QString>("expectedGuard");
|
||||
|
||||
QTest::newRow("default template, .h")
|
||||
<< QString() << QString("/tmp/header.h") << QString("HEADER_H");
|
||||
QTest::newRow("default template, .hpp")
|
||||
<< QString() << QString("/tmp/header.hpp") << QString("HEADER_HPP");
|
||||
QTest::newRow("default template, two extensions")
|
||||
<< QString() << QString("/tmp/header.in.h") << QString("HEADER_IN_H");
|
||||
QTest::newRow("non-default template")
|
||||
<< QString("%{JS: '%{Header:FilePath}'.toUpperCase().replace(/[.]/, '_').replace(/[/]/g, '_')}")
|
||||
<< QString("/tmp/header.h") << QString("_TMP_HEADER_H");
|
||||
}
|
||||
|
||||
void testHeaderGuard()
|
||||
{
|
||||
QFETCH(QString, guardTemplate);
|
||||
QFETCH(QString, headerFile);
|
||||
QFETCH(QString, expectedGuard);
|
||||
|
||||
CppFileSettings settings;
|
||||
if (!guardTemplate.isEmpty())
|
||||
settings.headerGuardTemplate = guardTemplate;
|
||||
QCOMPARE(settings.headerGuard(FilePath::fromUserInput(headerFile)), expectedGuard);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
#endif // WITH_TESTS
|
||||
|
||||
void setupCppFileSettings(ExtensionSystem::IPlugin &plugin)
|
||||
{
|
||||
static CppFileSettingsProjectPanelFactory theCppFileSettingsProjectPanelFactory;
|
||||
|
||||
static CppFileSettingsPage theCppFileSettingsPage;
|
||||
|
||||
globalCppFileSettings().fromSettings(Core::ICore::settings());
|
||||
globalCppFileSettings().addMimeInitializer();
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
plugin.addTestCreator([] { return new CppFileSettingsTest; });
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace CppEditor::Internal
|
||||
|
||||
#include <cppfilesettingspage.moc>
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <QDir>
|
||||
|
||||
namespace ExtensionSystem { class IPlugin; }
|
||||
namespace ProjectExplorer { class Project; }
|
||||
|
||||
namespace CppEditor::Internal {
|
||||
@@ -28,6 +29,7 @@ public:
|
||||
QDir::toNativeSeparators("../Src"),
|
||||
".."};
|
||||
Utils::FilePath licenseTemplatePath;
|
||||
QString headerGuardTemplate = "%{JS: '%{Header:FileName}'.toUpperCase().replace(/[.]/g, '_')}";
|
||||
bool headerPragmaOnce = false;
|
||||
bool lowerCaseFiles = Constants::LOWERCASE_CPPFILES_DEFAULT;
|
||||
|
||||
@@ -39,6 +41,9 @@ public:
|
||||
// Convenience to return a license template completely formatted.
|
||||
QString licenseTemplate() const;
|
||||
|
||||
// Expanded headerGuardTemplate.
|
||||
QString headerGuard(const Utils::FilePath &headerFilePath) const;
|
||||
|
||||
bool equals(const CppFileSettings &rhs) const;
|
||||
bool operator==(const CppFileSettings &s) const { return equals(s); }
|
||||
bool operator!=(const CppFileSettings &s) const { return !equals(s); }
|
||||
@@ -48,6 +53,6 @@ CppFileSettings &globalCppFileSettings();
|
||||
|
||||
CppFileSettings cppFileSettingsForProject(ProjectExplorer::Project *project);
|
||||
|
||||
void setupCppFileSettings();
|
||||
void setupCppFileSettings(ExtensionSystem::IPlugin &plugin);
|
||||
|
||||
} // namespace CppEditor::Internal
|
||||
|
@@ -42,7 +42,7 @@ static QString fileName(const QString &path, const QString &extension)
|
||||
|
||||
QString CppToolsJsExtension::headerGuard(const QString &in) const
|
||||
{
|
||||
return Utils::headerGuard(in);
|
||||
return fileSettings().headerGuard(Utils::FilePath::fromString(in));
|
||||
}
|
||||
|
||||
QString CppToolsJsExtension::licenseTemplate() const
|
||||
|
@@ -358,6 +358,11 @@ CppCompletionAssistProcessor *getCppCompletionAssistProcessor()
|
||||
return new Internal::InternalCppCompletionAssistProcessor();
|
||||
}
|
||||
|
||||
QString deriveHeaderGuard(const Utils::FilePath &filePath, ProjectExplorer::Project *project)
|
||||
{
|
||||
return Internal::cppFileSettingsForProject(project).headerGuard(filePath);
|
||||
}
|
||||
|
||||
bool fileSizeExceedsLimit(const FilePath &filePath, int sizeLimitInMb)
|
||||
{
|
||||
if (sizeLimitInMb <= 0)
|
||||
|
@@ -6,7 +6,6 @@
|
||||
#include "cppeditor_global.h"
|
||||
|
||||
#include "clangdiagnosticconfig.h"
|
||||
#include "compileroptionsbuilder.h"
|
||||
#include "projectpart.h"
|
||||
|
||||
#include <texteditor/quickfix.h>
|
||||
@@ -65,6 +64,9 @@ quickFixOperations(const TextEditor::AssistInterface *interface);
|
||||
|
||||
CppCompletionAssistProcessor CPPEDITOR_EXPORT *getCppCompletionAssistProcessor();
|
||||
|
||||
QString CPPEDITOR_EXPORT
|
||||
deriveHeaderGuard(const Utils::FilePath &filePath, ProjectExplorer::Project *project);
|
||||
|
||||
enum class CacheUsage { ReadWrite, ReadOnly };
|
||||
|
||||
Utils::FilePath CPPEDITOR_EXPORT correspondingHeaderOrSource(
|
||||
|
@@ -388,7 +388,7 @@ private:
|
||||
= Utils::transform<QStringList>(state->namespacePath, [&](const Namespace *ns) {
|
||||
return ov.prettyName(ns->name());
|
||||
});
|
||||
const QString headerGuard = Utils::headerGuard(headerFileName);
|
||||
const QString headerGuard = fileSettings.headerGuard(headerFilePath);
|
||||
if (fileSettings.headerPragmaOnce) {
|
||||
headerContent.append("#pragma once\n");
|
||||
} else {
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <cppeditor/abstracteditorsupport.h>
|
||||
#include <cppeditor/cpptoolsreuse.h>
|
||||
#include <projectexplorer/projecttree.h>
|
||||
#include <qtsupport/codegenerator.h>
|
||||
#include <qtsupport/codegensettings.h>
|
||||
@@ -75,7 +76,8 @@ bool QtDesignerFormClassCodeGenerator::generateCpp(const FormClassWizardParamete
|
||||
const QString sourceLicense = CppEditor::AbstractEditorSupport::licenseTemplate(
|
||||
project, FilePath::fromString(parameters.sourceFile), parameters.className);
|
||||
// Include guards
|
||||
const QString guard = Utils::headerGuard(parameters.headerFile);
|
||||
const QString guard
|
||||
= CppEditor::deriveHeaderGuard(FilePath::fromString(parameters.headerFile), project);
|
||||
|
||||
const QString uiInclude = "ui_" + QFileInfo(parameters.uiFile).completeBaseName() + ".h";
|
||||
|
||||
|
Reference in New Issue
Block a user