forked from qt-creator/qt-creator
Utils: Centralize aspect macro expansion setup and handling
Let each aspect have a macro expander, and let aspect-owned lineedits use this for expansion. Change-Id: Ifa6f5a678cf81c169643e4145f41e69eafedeb93 Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "guard.h"
|
||||
#include "iconbutton.h"
|
||||
#include "layoutbuilder.h"
|
||||
#include "macroexpander.h"
|
||||
#include "passworddialog.h"
|
||||
#include "pathchooser.h"
|
||||
#include "pathlisteditor.h"
|
||||
@@ -95,6 +96,7 @@ public:
|
||||
BaseAspect::DataCloner m_dataCloner;
|
||||
QList<BaseAspect::DataExtractor> m_dataExtractors;
|
||||
|
||||
MacroExpander *m_expander = globalMacroExpander();
|
||||
QUndoStack *m_undoStack = nullptr;
|
||||
};
|
||||
|
||||
@@ -724,6 +726,27 @@ QVariant BaseAspect::fromSettingsValue(const QVariant &val) const
|
||||
return d->m_fromSettings ? d->m_fromSettings(val) : val;
|
||||
}
|
||||
|
||||
void BaseAspect::setMacroExpander(MacroExpander *expander)
|
||||
{
|
||||
d->m_expander = expander;
|
||||
}
|
||||
|
||||
MacroExpander *BaseAspect::macroExpander() const
|
||||
{
|
||||
return d->m_expander;
|
||||
}
|
||||
|
||||
void BaseAspect::addMacroExpansion(QWidget *w)
|
||||
{
|
||||
if (!d->m_expander)
|
||||
return;
|
||||
const auto chooser = new VariableChooser(w);
|
||||
chooser->addSupportedWidget(w);
|
||||
chooser->addMacroExpanderProvider([this] { return d->m_expander; });
|
||||
if (auto pathChooser = qobject_cast<PathChooser *>(w))
|
||||
pathChooser->setMacroExpander(d->m_expander);
|
||||
}
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class BoolAspectPrivate
|
||||
@@ -887,7 +910,6 @@ public:
|
||||
Qt::TextElideMode m_elideMode = Qt::ElideNone;
|
||||
QString m_placeHolderText;
|
||||
Key m_historyCompleterKey;
|
||||
MacroExpanderProvider m_expanderProvider;
|
||||
StringAspect::ValueAcceptor m_valueAcceptor;
|
||||
std::optional<FancyLineEdit::ValidationFunction> m_validator;
|
||||
|
||||
@@ -1119,16 +1141,6 @@ void StringAspect::setAcceptRichText(bool acceptRichText)
|
||||
emit acceptRichTextChanged(acceptRichText);
|
||||
}
|
||||
|
||||
void StringAspect::setMacroExpanderProvider(const MacroExpanderProvider &expanderProvider)
|
||||
{
|
||||
d->m_expanderProvider = expanderProvider;
|
||||
}
|
||||
|
||||
void StringAspect::setUseGlobalMacroExpander()
|
||||
{
|
||||
d->m_expanderProvider = &globalMacroExpander;
|
||||
}
|
||||
|
||||
void StringAspect::setUseResetButton()
|
||||
{
|
||||
d->m_useResetButton = true;
|
||||
@@ -1149,14 +1161,6 @@ void StringAspect::addToLayout(Layout &parent)
|
||||
{
|
||||
d->m_checkerImpl.addToLayoutFirst(parent);
|
||||
|
||||
const auto useMacroExpander = [this](QWidget *w) {
|
||||
if (!d->m_expanderProvider)
|
||||
return;
|
||||
const auto chooser = new VariableChooser(w);
|
||||
chooser->addSupportedWidget(w);
|
||||
chooser->addMacroExpanderProvider(d->m_expanderProvider);
|
||||
};
|
||||
|
||||
const QString displayedString = d->m_displayFilter ? d->m_displayFilter(volatileValue())
|
||||
: volatileValue();
|
||||
|
||||
@@ -1164,6 +1168,7 @@ void StringAspect::addToLayout(Layout &parent)
|
||||
case PasswordLineEditDisplay:
|
||||
case LineEditDisplay: {
|
||||
auto lineEditDisplay = createSubWidget<FancyLineEdit>();
|
||||
addMacroExpansion(lineEditDisplay);
|
||||
lineEditDisplay->setPlaceholderText(d->m_placeHolderText);
|
||||
if (!d->m_historyCompleterKey.isEmpty())
|
||||
lineEditDisplay->setHistoryCompleter(d->m_historyCompleterKey);
|
||||
@@ -1197,7 +1202,6 @@ void StringAspect::addToLayout(Layout &parent)
|
||||
}
|
||||
|
||||
addLabeledItem(parent, lineEditDisplay);
|
||||
useMacroExpander(lineEditDisplay);
|
||||
if (d->m_useResetButton) {
|
||||
auto resetButton = createSubWidget<QPushButton>(Tr::tr("Reset"));
|
||||
resetButton->setEnabled(lineEditDisplay->text() != defaultValue());
|
||||
@@ -1255,6 +1259,7 @@ void StringAspect::addToLayout(Layout &parent)
|
||||
}
|
||||
case TextEditDisplay: {
|
||||
auto textEditDisplay = createSubWidget<QTextEdit>();
|
||||
addMacroExpansion(textEditDisplay);
|
||||
textEditDisplay->setPlaceholderText(d->m_placeHolderText);
|
||||
textEditDisplay->setUndoRedoEnabled(false);
|
||||
textEditDisplay->setAcceptRichText(d->m_acceptRichText);
|
||||
@@ -1273,7 +1278,6 @@ void StringAspect::addToLayout(Layout &parent)
|
||||
}
|
||||
|
||||
addLabeledItem(parent, textEditDisplay);
|
||||
useMacroExpander(textEditDisplay);
|
||||
bufferToGui();
|
||||
connect(this,
|
||||
&StringAspect::acceptRichTextChanged,
|
||||
@@ -1323,8 +1327,10 @@ void StringAspect::addToLayout(Layout &parent)
|
||||
|
||||
QString StringAspect::expandedValue() const
|
||||
{
|
||||
if (!m_internal.isEmpty() && d->m_expanderProvider)
|
||||
return d->m_expanderProvider()->expand(m_internal);
|
||||
if (!m_internal.isEmpty()) {
|
||||
if (auto expander = macroExpander())
|
||||
return expander->expand(m_internal);
|
||||
}
|
||||
return m_internal;
|
||||
}
|
||||
|
||||
@@ -1406,7 +1412,6 @@ public:
|
||||
PathChooser::Kind m_expectedKind = PathChooser::File;
|
||||
Environment m_environment;
|
||||
QPointer<PathChooser> m_pathChooserDisplay;
|
||||
MacroExpanderProvider m_expanderProvider;
|
||||
FilePath m_baseFileName;
|
||||
StringAspect::ValueAcceptor m_valueAcceptor;
|
||||
std::optional<FancyLineEdit::ValidationFunction> m_validator;
|
||||
@@ -1453,8 +1458,10 @@ FilePath FilePathAspect::operator()() const
|
||||
FilePath FilePathAspect::expandedValue() const
|
||||
{
|
||||
const auto value = TypedAspect::value();
|
||||
if (!value.isEmpty() && d->m_expanderProvider)
|
||||
return FilePath::fromUserInput(d->m_expanderProvider()->expand(value));
|
||||
if (!value.isEmpty()) {
|
||||
if (auto expander = macroExpander())
|
||||
return FilePath::fromUserInput(expander->expand(value));
|
||||
}
|
||||
return FilePath::fromUserInput(value);
|
||||
}
|
||||
|
||||
@@ -1586,17 +1593,10 @@ void FilePathAspect::addToLayout(Layouting::Layout &parent)
|
||||
{
|
||||
d->m_checkerImpl.addToLayoutFirst(parent);
|
||||
|
||||
const auto useMacroExpander = [this](QWidget *w) {
|
||||
if (!d->m_expanderProvider)
|
||||
return;
|
||||
const auto chooser = new VariableChooser(w);
|
||||
chooser->addSupportedWidget(w);
|
||||
chooser->addMacroExpanderProvider(d->m_expanderProvider);
|
||||
};
|
||||
|
||||
const QString displayedString = d->m_displayFilter ? d->m_displayFilter(value()) : value();
|
||||
|
||||
d->m_pathChooserDisplay = createSubWidget<PathChooser>();
|
||||
addMacroExpansion(d->m_pathChooserDisplay->lineEdit());
|
||||
d->m_pathChooserDisplay->setExpectedKind(d->m_expectedKind);
|
||||
if (!d->m_historyCompleterKey.isEmpty())
|
||||
d->m_pathChooserDisplay->setHistoryCompleter(d->m_historyCompleterKey);
|
||||
@@ -1621,7 +1621,6 @@ void FilePathAspect::addToLayout(Layouting::Layout &parent)
|
||||
d->m_pathChooserDisplay->lineEdit()->setPlaceholderText(d->m_placeHolderText);
|
||||
d->m_checkerImpl.updateWidgetFromCheckStatus(this, d->m_pathChooserDisplay.data());
|
||||
addLabeledItem(parent, d->m_pathChooserDisplay);
|
||||
useMacroExpander(d->m_pathChooserDisplay->lineEdit());
|
||||
connect(d->m_pathChooserDisplay, &PathChooser::validChanged, this, &FilePathAspect::validChanged);
|
||||
bufferToGui();
|
||||
if (isAutoApply() && d->m_autoApplyOnEditingFinished) {
|
||||
@@ -1765,11 +1764,6 @@ void FilePathAspect::setHistoryCompleter(const Key &historyCompleterKey)
|
||||
d->m_pathChooserDisplay->setHistoryCompleter(historyCompleterKey);
|
||||
}
|
||||
|
||||
void FilePathAspect::setMacroExpanderProvider(const MacroExpanderProvider &expanderProvider)
|
||||
{
|
||||
d->m_expanderProvider = expanderProvider;
|
||||
}
|
||||
|
||||
void FilePathAspect::validateInput()
|
||||
{
|
||||
if (d->m_pathChooserDisplay)
|
||||
@@ -3237,6 +3231,14 @@ void AspectContainer::setUndoStack(QUndoStack *undoStack)
|
||||
aspect->setUndoStack(undoStack);
|
||||
}
|
||||
|
||||
void AspectContainer::setMacroExpander(MacroExpander *expander)
|
||||
{
|
||||
BaseAspect::setMacroExpander(expander);
|
||||
|
||||
for (BaseAspect *aspect : std::as_const(d->m_items))
|
||||
aspect->setMacroExpander(expander);
|
||||
}
|
||||
|
||||
bool AspectContainer::equals(const AspectContainer &other) const
|
||||
{
|
||||
// FIXME: Expensive, but should not really be needed in a fully aspectified world.
|
||||
|
@@ -7,7 +7,6 @@
|
||||
#include "guiutils.h"
|
||||
#include "id.h"
|
||||
#include "infolabel.h"
|
||||
#include "macroexpander.h"
|
||||
#include "pathchooser.h"
|
||||
#include "qtcsettings.h"
|
||||
#include "store.h"
|
||||
@@ -36,6 +35,7 @@ namespace Utils {
|
||||
class AspectContainer;
|
||||
class BoolAspect;
|
||||
class CheckableDecider;
|
||||
class MacroExpander;
|
||||
|
||||
namespace Internal {
|
||||
class AspectContainerPrivate;
|
||||
@@ -202,6 +202,9 @@ public:
|
||||
// This is expensive. Do not use without good reason
|
||||
void writeToSettingsImmediatly() const;
|
||||
|
||||
void setMacroExpander(MacroExpander *expander);
|
||||
MacroExpander *macroExpander() const;
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
void volatileValueChanged();
|
||||
@@ -219,6 +222,8 @@ protected:
|
||||
|
||||
virtual void handleGuiChanged();
|
||||
|
||||
void addMacroExpansion(QWidget *w);
|
||||
|
||||
QLabel *createLabel();
|
||||
void addLabeledItem(Layouting::Layout &parent, QWidget *widget);
|
||||
|
||||
@@ -607,8 +612,6 @@ public:
|
||||
void setPlaceHolderText(const QString &placeHolderText);
|
||||
void setHistoryCompleter(const Key &historyCompleterKey);
|
||||
void setAcceptRichText(bool acceptRichText);
|
||||
void setMacroExpanderProvider(const MacroExpanderProvider &expanderProvider);
|
||||
void setUseGlobalMacroExpander();
|
||||
void setUseResetButton();
|
||||
void setValidationFunction(const FancyLineEdit::ValidationFunction &validator);
|
||||
void setAutoApplyOnEditingFinished(bool applyOnEditingFinished);
|
||||
@@ -685,7 +688,6 @@ public:
|
||||
void setValidationFunction(const FancyLineEdit::ValidationFunction &validator);
|
||||
void setDisplayFilter(const std::function<QString (const QString &)> &displayFilter);
|
||||
void setHistoryCompleter(const Key &historyCompleterKey);
|
||||
void setMacroExpanderProvider(const MacroExpanderProvider &expanderProvider);
|
||||
void setShowToolTipOnLabel(bool show);
|
||||
void setAutoApplyOnEditingFinished(bool applyOnEditingFinished);
|
||||
|
||||
@@ -975,6 +977,8 @@ public:
|
||||
bool isDirty() override;
|
||||
void setUndoStack(QUndoStack *undoStack) override;
|
||||
|
||||
void setMacroExpander(MacroExpander *expander);
|
||||
|
||||
template <typename T> T *aspect() const
|
||||
{
|
||||
for (BaseAspect *aspect : aspects())
|
||||
|
@@ -5,7 +5,6 @@
|
||||
|
||||
#include "utils_global.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QList>
|
||||
|
||||
#include <functional>
|
||||
|
@@ -1463,12 +1463,9 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id)
|
||||
buildTypeAspect.setDisplayStyle(StringAspect::LineEditDisplay);
|
||||
buildTypeAspect.setDefaultValue("Unknown");
|
||||
|
||||
initialCMakeArguments.setMacroExpanderProvider([this] { return macroExpander(); });
|
||||
|
||||
additionalCMakeOptions.setSettingsKey("CMake.Additional.Options");
|
||||
additionalCMakeOptions.setLabelText(Tr::tr("Additional CMake <a href=\"options\">options</a>:"));
|
||||
additionalCMakeOptions.setDisplayStyle(StringAspect::LineEditDisplay);
|
||||
additionalCMakeOptions.setMacroExpanderProvider([this] { return macroExpander(); });
|
||||
|
||||
macroExpander()->registerVariable(DEVELOPMENT_TEAM_FLAG,
|
||||
Tr::tr("The CMake flag for the development team"),
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/macroexpander.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
#include <utils/processinfo.h>
|
||||
#include <utils/processinterface.h>
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include <utils/clangutils.h>
|
||||
#include <utils/itemviews.h>
|
||||
#include <utils/layoutbuilder.h>
|
||||
#include <utils/macroexpander.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
#include <utils/variablechooser.h>
|
||||
|
||||
@@ -207,17 +208,17 @@ FilePath ClangdSettings::clangdFilePath() const
|
||||
return fallbackClangdFilePath();
|
||||
}
|
||||
|
||||
FilePath ClangdSettings::projectIndexPath(const Utils::MacroExpander &expander) const
|
||||
FilePath ClangdSettings::projectIndexPath(const MacroExpander &expander) const
|
||||
{
|
||||
return FilePath::fromUserInput(expander.expand(m_data.projectIndexPathTemplate));
|
||||
}
|
||||
|
||||
FilePath ClangdSettings::sessionIndexPath(const Utils::MacroExpander &expander) const
|
||||
FilePath ClangdSettings::sessionIndexPath(const MacroExpander &expander) const
|
||||
{
|
||||
return FilePath::fromUserInput(expander.expand(m_data.sessionIndexPathTemplate));
|
||||
}
|
||||
|
||||
bool ClangdSettings::sizeIsOkay(const Utils::FilePath &fp) const
|
||||
bool ClangdSettings::sizeIsOkay(const FilePath &fp) const
|
||||
{
|
||||
return !sizeThresholdEnabled() || sizeThresholdInKb() * 1024 >= fp.fileSize();
|
||||
}
|
||||
|
@@ -266,7 +266,6 @@ LocalsAndExpressionsSettings::LocalsAndExpressionsSettings()
|
||||
|
||||
extraDumperCommands.setSettingsKey(debugModeGroup, "GdbCustomDumperCommands");
|
||||
extraDumperCommands.setDisplayStyle(StringAspect::TextEditDisplay);
|
||||
extraDumperCommands.setUseGlobalMacroExpander();
|
||||
extraDumperCommands.setToolTip("<html><head/><body><p>"
|
||||
+ Tr::tr("Python commands entered here will be executed after built-in "
|
||||
"debugging helpers have been loaded and fully initialized. You can "
|
||||
|
@@ -127,7 +127,6 @@ GdbSettings::GdbSettings()
|
||||
|
||||
gdbStartupCommands.setSettingsKey(debugModeGroup, "GdbStartupCommands");
|
||||
gdbStartupCommands.setDisplayStyle(StringAspect::TextEditDisplay);
|
||||
gdbStartupCommands.setUseGlobalMacroExpander();
|
||||
gdbStartupCommands.setToolTip("<html><head/><body><p>" + Tr::tr(
|
||||
"GDB commands entered here will be executed after "
|
||||
"GDB has been started, but before the debugged program is started or "
|
||||
@@ -136,7 +135,6 @@ GdbSettings::GdbSettings()
|
||||
|
||||
gdbPostAttachCommands.setSettingsKey(debugModeGroup, "GdbPostAttachCommands");
|
||||
gdbPostAttachCommands.setDisplayStyle(StringAspect::TextEditDisplay);
|
||||
gdbPostAttachCommands.setUseGlobalMacroExpander();
|
||||
gdbPostAttachCommands.setToolTip("<html><head/><body><p>" + Tr::tr(
|
||||
"GDB commands entered here will be executed after "
|
||||
"GDB has successfully attached to remote targets.</p>"
|
||||
|
@@ -194,7 +194,6 @@ BuildConfiguration::BuildConfiguration(Target *target, Utils::Id id)
|
||||
|
||||
d->m_buildDirectoryAspect.setBaseFileName(target->project()->projectDirectory());
|
||||
d->m_buildDirectoryAspect.setEnvironment(environment());
|
||||
d->m_buildDirectoryAspect.setMacroExpanderProvider([this] { return macroExpander(); });
|
||||
connect(&d->m_buildDirectoryAspect, &StringAspect::changed,
|
||||
this, &BuildConfiguration::emitBuildDirectoryChanged);
|
||||
connect(this, &BuildConfiguration::environmentChanged, this, [this] {
|
||||
|
@@ -59,7 +59,6 @@ BuildPropertiesSettings::BuildPropertiesSettings()
|
||||
"The default value can be set using the environment variable "
|
||||
"<tt>%1</tt>")
|
||||
.arg(Constants::QTC_DEFAULT_BUILD_DIRECTORY_TEMPLATE));
|
||||
buildDirectoryTemplate.setUseGlobalMacroExpander();
|
||||
buildDirectoryTemplate.setUseResetButton();
|
||||
|
||||
separateDebugInfo.setSettingsKey("ProjectExplorer/Settings/SeparateDebugInfo");
|
||||
|
@@ -85,6 +85,9 @@ BuildStep::BuildStep(BuildStepList *bsl, Id id)
|
||||
: ProjectConfiguration(bsl->target(), id)
|
||||
, m_stepList(bsl)
|
||||
{
|
||||
if (auto bc = buildConfiguration())
|
||||
setMacroExpander(bc->macroExpander());
|
||||
|
||||
connect(this, &ProjectConfiguration::displayNameChanged, this, &BuildStep::updateSummary);
|
||||
}
|
||||
|
||||
@@ -120,12 +123,8 @@ QWidget *BuildStep::createConfigWidget()
|
||||
form.flush();
|
||||
}
|
||||
}
|
||||
auto widget = form.emerge();
|
||||
|
||||
if (m_addMacroExpander)
|
||||
VariableChooser::addSupportForChildWidgets(widget, macroExpander());
|
||||
|
||||
return widget;
|
||||
return form.emerge();
|
||||
}
|
||||
|
||||
void BuildStep::fromMap(const Store &map)
|
||||
@@ -196,13 +195,6 @@ BuildConfiguration::BuildType BuildStep::buildType() const
|
||||
return BuildConfiguration::Unknown;
|
||||
}
|
||||
|
||||
MacroExpander *BuildStep::macroExpander() const
|
||||
{
|
||||
if (auto bc = buildConfiguration())
|
||||
return bc->macroExpander();
|
||||
return globalMacroExpander();
|
||||
}
|
||||
|
||||
QString BuildStep::fallbackWorkingDirectory() const
|
||||
{
|
||||
if (buildConfiguration())
|
||||
|
@@ -52,7 +52,6 @@ public:
|
||||
|
||||
BuildSystem *buildSystem() const;
|
||||
BuildConfiguration::BuildType buildType() const;
|
||||
Utils::MacroExpander *macroExpander() const;
|
||||
|
||||
enum class OutputFormat {
|
||||
Stdout, Stderr, // These are for forwarded output from external tools
|
||||
@@ -99,7 +98,6 @@ protected:
|
||||
void setWidgetExpandedByDefault(bool widgetExpandedByDefault);
|
||||
void setImmutable(bool immutable) { m_immutable = immutable; }
|
||||
void setSummaryUpdater(const std::function<QString()> &summaryUpdater);
|
||||
void addMacroExpander() { m_addMacroExpander = true; }
|
||||
void setSummaryText(const QString &summaryText);
|
||||
|
||||
DeployConfiguration *deployConfiguration() const;
|
||||
@@ -119,7 +117,6 @@ private:
|
||||
bool m_enabled = true;
|
||||
bool m_immutable = false;
|
||||
bool m_widgetExpandedByDefault = true;
|
||||
bool m_addMacroExpander = false;
|
||||
std::optional<bool> m_wasExpanded;
|
||||
std::function<QString()> m_summaryUpdater;
|
||||
|
||||
|
@@ -25,13 +25,9 @@ public:
|
||||
{
|
||||
m_sourceAspect.setSettingsKey(SOURCE_KEY);
|
||||
m_sourceAspect.setLabelText(Tr::tr("Source:"));
|
||||
m_sourceAspect.setMacroExpanderProvider([this] { return macroExpander(); });
|
||||
|
||||
m_targetAspect.setSettingsKey(TARGET_KEY);
|
||||
m_targetAspect.setLabelText(Tr::tr("Target:"));
|
||||
m_targetAspect.setMacroExpanderProvider([this] { return macroExpander(); });
|
||||
|
||||
addMacroExpander();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@@ -60,8 +60,6 @@ public:
|
||||
setupProcessParameters(¶m);
|
||||
return param.summary(display);
|
||||
});
|
||||
|
||||
addMacroExpander();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "target.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/macroexpander.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
@@ -180,8 +180,6 @@ public:
|
||||
executable.setLabelText(Tr::tr("Executable:"));
|
||||
executable.setReadOnly(true);
|
||||
executable.setValue(bti.targetFilePath);
|
||||
executable.setMacroExpanderProvider(
|
||||
[this]() -> MacroExpander * { return const_cast<MacroExpander *>(macroExpander()); });
|
||||
|
||||
auto argumentsAsString = [this]() {
|
||||
return CommandLine{
|
||||
|
@@ -31,8 +31,6 @@ public:
|
||||
commandLine.setHistoryCompleter("RemoteLinuxCustomCommandDeploymentStep.History");
|
||||
|
||||
setInternalInitializer([this] { return isDeploymentPossible(); });
|
||||
|
||||
addMacroExpander();
|
||||
}
|
||||
|
||||
expected_str<void> isDeploymentPossible() const final;
|
||||
|
Reference in New Issue
Block a user