Wizards: add a warning about unsupported keys

- parseData methods check that there is no unknown key is used
 - showing the name and type might be useful in warning and error messages

Change-Id: I1371bb3af1ad48ed4b85260f3b1309cdba1cb71f
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Tim Jenssen
2017-10-19 07:43:05 +02:00
parent 2382824d7b
commit 2f3acee4e0
3 changed files with 121 additions and 57 deletions

View File

@@ -61,6 +61,31 @@ const char DATA_KEY[] = "data";
const char IS_COMPLETE_KEY[] = "isComplete";
const char IS_COMPLETE_MESSAGE_KEY[] = "trIncompleteMessage";
namespace {
QVariant consumeValue(QVariantMap &map, const QString &key, const QVariant &defaultValue = QVariant())
{
QVariantMap::iterator i = map.find(key);
if (i != map.end()) {
QVariant value = i.value();
map.erase(i);
return value;
}
return defaultValue;
}
void warnAboutUnsupportedKeys(const QVariantMap &map, const QString &name, const QString &type = QString())
{
if (!map.isEmpty()) {
QString typeAndName = name;
if (!type.isEmpty() && !name.isEmpty())
typeAndName = QString("%1(\"%2\")").arg(type, name);
qWarning().noquote() << QString("Field %1 has unsupported keys: %2").arg(typeAndName, map.keys().join(", "));
}
}
} // namespace
namespace ProjectExplorer {
// --------------------------------------------------------------------
@@ -120,6 +145,11 @@ JsonFieldPage::Field::~Field()
delete d;
}
QString JsonFieldPage::Field::type()
{
return d->m_type;
}
JsonFieldPage::Field *JsonFieldPage::Field::parse(const QVariant &input, QString *errorMessage)
{
if (input.type() != QVariant::Map) {
@@ -129,13 +159,13 @@ JsonFieldPage::Field *JsonFieldPage::Field::parse(const QVariant &input, QString
}
QVariantMap tmp = input.toMap();
const QString name = tmp.value(NAME_KEY).toString();
const QString name = consumeValue(tmp, NAME_KEY).toString();
if (name.isEmpty()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"Field has no name.");
return 0;
}
const QString type = tmp.value(TYPE_KEY).toString();
const QString type = consumeValue(tmp, TYPE_KEY).toString();
if (type.isEmpty()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"Field \"%1\" has no type.").arg(name);
@@ -150,17 +180,17 @@ JsonFieldPage::Field *JsonFieldPage::Field::parse(const QVariant &input, QString
return 0;
}
data->setTexts(name,
JsonWizardFactory::localizedString(tmp.value(DISPLAY_NAME_KEY).toString()),
tmp.value(TOOLTIP_KEY).toString());
JsonWizardFactory::localizedString(consumeValue(tmp, DISPLAY_NAME_KEY).toString()),
consumeValue(tmp, TOOLTIP_KEY).toString());
data->setVisibleExpression(tmp.value(VISIBLE_KEY, true));
data->setEnabledExpression(tmp.value(ENABLED_KEY, true));
data->setIsMandatory(tmp.value(MANDATORY_KEY, true).toBool());
data->setHasSpan(tmp.value(SPAN_KEY, false).toBool());
data->setIsCompleteExpando(tmp.value(IS_COMPLETE_KEY, true),
tmp.value(IS_COMPLETE_MESSAGE_KEY).toString());
data->setVisibleExpression(consumeValue(tmp, VISIBLE_KEY, true));
data->setEnabledExpression(consumeValue(tmp, ENABLED_KEY, true));
data->setIsMandatory(consumeValue(tmp, MANDATORY_KEY, true).toBool());
data->setHasSpan(consumeValue(tmp, SPAN_KEY, false).toBool());
data->setIsCompleteExpando(consumeValue(tmp, IS_COMPLETE_KEY, true),
consumeValue(tmp, IS_COMPLETE_MESSAGE_KEY).toString());
QVariant dataVal = tmp.value(DATA_KEY);
QVariant dataVal = consumeValue(tmp, DATA_KEY);
if (!data->parseData(dataVal, errorMessage)) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"When parsing Field \"%1\": %2")
@@ -169,6 +199,7 @@ JsonFieldPage::Field *JsonFieldPage::Field::parse(const QVariant &input, QString
return 0;
}
warnAboutUnsupportedKeys(tmp, name);
return data;
}
@@ -217,6 +248,11 @@ void JsonFieldPage::Field::setVisible(bool v)
d->m_widget->setVisible(v);
}
void JsonFieldPage::Field::setType(const QString &type)
{
d->m_type = type;
}
bool JsonFieldPage::Field::validate(MacroExpander *expander, QString *message)
{
if (!JsonWizard::boolFromVariant(d->m_isCompleteExpando, expander)) {
@@ -322,21 +358,23 @@ bool LabelField::parseData(const QVariant &data, QString *errorMessage)
{
if (data.type() != QVariant::Map) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"Label data is not an object.");
"Label(\"%1\") data is not an object.")
.arg(name());
return false;
}
QVariantMap tmp = data.toMap();
m_wordWrap = tmp.value("wordWrap", false).toBool();
m_text = JsonWizardFactory::localizedString(tmp.value("trText"));
m_wordWrap = consumeValue(tmp, "wordWrap", false).toBool();
m_text = JsonWizardFactory::localizedString(consumeValue(tmp, "trText"));
if (m_text.isEmpty()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"No text given for Label.");
"Label(\"%1\") has no trText.")
.arg(name());
return false;
}
warnAboutUnsupportedKeys(tmp, name(), type());
return true;
}
@@ -361,20 +399,23 @@ bool SpacerField::parseData(const QVariant &data, QString *errorMessage)
if (data.type() != QVariant::Map) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"Spacer data is not an object.");
"Spacer(\"%1\") data is not an object.")
.arg(name());
return false;
}
QVariantMap tmp = data.toMap();
bool ok;
m_factor = tmp.value("factor", 1).toInt(&ok);
m_factor = consumeValue(tmp, "factor", 1).toInt(&ok);
if (!ok) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"\"factor\" is no integer value.");
"Spacer(\"%1\") property \"factor\" is no integer value.")
.arg(name());
return false;
}
warnAboutUnsupportedKeys(tmp, name(), type());
return true;
}
@@ -403,30 +444,33 @@ bool LineEditField::parseData(const QVariant &data, QString *errorMessage)
if (data.type() != QVariant::Map) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"LineEdit data is not an object.");
"LineEdit(\"%1\") data is not an object.")
.arg(name());
return false;
}
QVariantMap tmp = data.toMap();
m_isPassword = tmp.value("isPassword", false).toBool();
m_defaultText = JsonWizardFactory::localizedString(tmp.value("trText").toString());
m_disabledText = JsonWizardFactory::localizedString(tmp.value("trDisabledText").toString());
m_placeholderText = JsonWizardFactory::localizedString(tmp.value("trPlaceholder").toString());
m_historyId = tmp.value("historyId").toString();
m_restoreLastHistoryItem = tmp.value("restoreLastHistoyItem", false).toBool();
QString pattern = tmp.value("validator").toString();
m_isPassword = consumeValue(tmp, "isPassword", false).toBool();
m_defaultText = JsonWizardFactory::localizedString(consumeValue(tmp, "trText").toString());
m_disabledText = JsonWizardFactory::localizedString(consumeValue(tmp, "trDisabledText").toString());
m_placeholderText = JsonWizardFactory::localizedString(consumeValue(tmp, "trPlaceholder").toString());
m_historyId = consumeValue(tmp, "historyId").toString();
m_restoreLastHistoryItem = consumeValue(tmp, "restoreLastHistoyItem", false).toBool();
QString pattern = consumeValue(tmp, "validator").toString();
if (!pattern.isEmpty()) {
m_validatorRegExp = QRegularExpression(pattern);
if (!m_validatorRegExp.isValid()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"Invalid regular expression \"%1\" in \"validator\".")
.arg(pattern);
"LineEdit(\"%1\") has an invalid regular expression \"%1\" in \"validator\".")
.arg(name(), pattern);
m_validatorRegExp = QRegularExpression();
return false;
}
}
m_fixupExpando = tmp.value("fixup").toString();
m_fixupExpando = consumeValue(tmp, "fixup").toString();
warnAboutUnsupportedKeys(tmp, name(), type());
return true;
}
@@ -515,16 +559,18 @@ bool TextEditField::parseData(const QVariant &data, QString *errorMessage)
if (data.type() != QVariant::Map) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"TextEdit data is not an object.");
"TextEdit(\"%1\") data is not an object.")
.arg(name());
return false;
}
QVariantMap tmp = data.toMap();
m_defaultText = JsonWizardFactory::localizedString(tmp.value("trText").toString());
m_disabledText = JsonWizardFactory::localizedString(tmp.value("trDisabledText").toString());
m_acceptRichText = tmp.value("richText", true).toBool();
m_defaultText = JsonWizardFactory::localizedString(consumeValue(tmp, "trText").toString());
m_disabledText = JsonWizardFactory::localizedString(consumeValue(tmp, "trDisabledText").toString());
m_acceptRichText = consumeValue(tmp, "richText", true).toBool();
warnAboutUnsupportedKeys(tmp, name(), type());
return true;
}
@@ -589,11 +635,11 @@ bool PathChooserField::parseData(const QVariant &data, QString *errorMessage)
QVariantMap tmp = data.toMap();
m_path = tmp.value("path").toString();
m_basePath = tmp.value("basePath").toString();
m_historyId = tmp.value("historyId").toString();
m_path = consumeValue(tmp, "path").toString();
m_basePath = consumeValue(tmp, "basePath").toString();
m_historyId = consumeValue(tmp, "historyId").toString();
QString kindStr = tmp.value("kind", "existingDirectory").toString();
QString kindStr = consumeValue(tmp, "kind", "existingDirectory").toString();
if (kindStr == "existingDirectory") {
m_kind = PathChooser::ExistingDirectory;
} else if (kindStr == "directory") {
@@ -617,6 +663,7 @@ bool PathChooserField::parseData(const QVariant &data, QString *errorMessage)
return false;
}
warnAboutUnsupportedKeys(tmp, name(), type());
return true;
}
@@ -680,21 +727,24 @@ bool CheckBoxField::parseData(const QVariant &data, QString *errorMessage)
if (data.type() != QVariant::Map) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"CheckBox data is not an object.");
"CheckBox(\"%1\") data is not an object.")
.arg(name());
return false;
}
QVariantMap tmp = data.toMap();
m_checkedValue = tmp.value("checkedValue", true).toString();
m_uncheckedValue = tmp.value("uncheckedValue", false).toString();
m_checkedValue = consumeValue(tmp, "checkedValue", true).toString();
m_uncheckedValue = consumeValue(tmp, "uncheckedValue", false).toString();
if (m_checkedValue == m_uncheckedValue) {
*errorMessage= QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"CheckBox values for checked and unchecked state are identical.");
"CheckBox(\"%1\") values for checked and unchecked state are identical.")
.arg(name());
return false;
}
m_checkedExpression = tmp.value("checked", false);
m_checkedExpression = consumeValue(tmp, "checked", false);
warnAboutUnsupportedKeys(tmp, name(), type());
return true;
}
@@ -763,9 +813,9 @@ ComboBoxItem parseComboBoxItem(const QVariant &item, QString *errorMessage)
return ComboBoxItem();
} else if (item.type() == QVariant::Map) {
QVariantMap tmp = item.toMap();
QString key = JsonWizardFactory::localizedString(tmp.value(QLatin1String("trKey"), QString()).toString());
QString value = tmp.value(QLatin1String("value"), QString()).toString();
QVariant condition = tmp.value(QLatin1String("condition"), true);
QString key = JsonWizardFactory::localizedString(consumeValue(tmp, QLatin1String("trKey"), QString()).toString());
QString value = consumeValue(tmp, QLatin1String("value"), QString()).toString();
QVariant condition = consumeValue(tmp, QLatin1String("condition"), true);
if (key.isNull() || key.isEmpty()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"No \"key\" found in ComboBox items.");
@@ -791,28 +841,32 @@ bool ComboBoxField::parseData(const QVariant &data, QString *errorMessage)
QVariantMap tmp = data.toMap();
bool ok;
m_index = tmp.value("index", 0).toInt(&ok);
m_index = consumeValue(tmp, "index", 0).toInt(&ok);
if (!ok) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"ComboBox \"index\" is not an integer value.");
"ComboBox(\"%1\") \"index\" is not an integer value.")
.arg(name());
return false;
}
m_disabledIndex = tmp.value("disabledIndex", -1).toInt(&ok);
m_disabledIndex = consumeValue(tmp, "disabledIndex", -1).toInt(&ok);
if (!ok) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"ComboBox \"disabledIndex\" is not an integer value.");
"ComboBox(\"%1\") \"disabledIndex\" is not an integer value.")
.arg(name());
return false;
}
QVariant value = tmp.value("items");
QVariant value = consumeValue(tmp, "items");
if (value.isNull()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"ComboBox \"items\" missing.");
"ComboBox(\"%1\") \"items\" missing.")
.arg(name());
return false;
}
if (value.type() != QVariant::List) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"ComboBox \"items\" is not a list.");
"ComboBox(\"%1\") \"items\" is not a list.")
.arg(name());
return false;
}
@@ -831,10 +885,11 @@ bool ComboBoxField::parseData(const QVariant &data, QString *errorMessage)
m_itemDataList.clear();
m_itemList.clear();
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"Internal Error: ComboBox items lists got mixed up.");
"Internal Error: ComboBox(\"%1\") items lists got mixed up.")
.arg(name());
return false;
}
warnAboutUnsupportedKeys(tmp, name(), type());
return true;
}
@@ -1010,8 +1065,11 @@ MacroExpander *JsonFieldPage::expander()
JsonFieldPage::Field *JsonFieldPage::createFieldData(const QString &type)
{
if (auto factory = m_factories.value(type))
return factory();
if (auto factory = m_factories.value(type)) {
JsonFieldPage::Field *field = factory();
field->setType(type);
return field;
}
return nullptr;
}