Don't imply args which can't be combined

Leads to more useful error messages if an unknown
argument has been specified.
This commit is contained in:
Martchus 2016-11-15 21:44:23 +01:00
parent 4c0a1d1169
commit bbb884da30
2 changed files with 33 additions and 2 deletions

View File

@ -252,10 +252,25 @@ bool Argument::isParentPresent() const
*
* If the argument is in conflict with an other argument this argument will be returned.
* Otherwise nullptr will be returned.
*
* \remarks Conflicts with main arguments aren't considered by this method!
*/
Argument *Argument::conflictsWithArgument() const
{
if(!isCombinable() && isPresent()) {
return isPresent() ? wouldConflictWithArgument() : nullptr;
}
/*!
* \brief Checks if this argument would conflict with other arguments if it was present.
*
* If the argument is in conflict with an other argument this argument will be returned.
* Otherwise nullptr will be returned.
*
* \remarks Conflicts with main arguments aren't considered by this method!
*/
Argument *Argument::wouldConflictWithArgument() const
{
if(!isCombinable()) {
for(Argument *parent : m_parents) {
for(Argument *sibling : parent->subArguments()) {
if(sibling != this && sibling->isPresent() && !sibling->isCombinable()) {
@ -448,6 +463,19 @@ void ArgumentParser::readArgs(int argc, const char * const *argv)
}
}
/*!
* \brief Checks whether at least one uncombinable main argument is present.
*/
bool ArgumentParser::isUncombinableMainArgPresent() const
{
for(const Argument *arg : m_mainArgs) {
if(!arg->isCombinable() && arg->isPresent()) {
return true;
}
}
return false;
}
#ifdef DEBUG_BUILD
/*!
* \brief Verifies the specified \a argument definitions.
@ -628,8 +656,9 @@ void ArgumentParser::readSpecifiedArgs(ArgumentVector &args, std::size_t &index,
// use the first default argument which is not already present if there is still no match
if(!matchingArg && (!completionMode || (argv + 1 != end))) {
const bool uncombinableMainArgPresent = parentArg ? false : isUncombinableMainArgPresent();
for(Argument *arg : args) {
if(arg->isImplicit() && !arg->isPresent()) {
if(arg->isImplicit() && !arg->isPresent() && !arg->wouldConflictWithArgument() && (!uncombinableMainArgPresent || !arg->isMainArgument())) {
(matchingArg = arg)->m_occurrences.emplace_back(index, parentPath, parentArg);
break;
}

View File

@ -183,6 +183,7 @@ public:
const char *preDefinedCompletionValues() const;
void setPreDefinedCompletionValues(const char *preDefinedCompletionValues);
Argument *conflictsWithArgument() const;
Argument *wouldConflictWithArgument() const;
void reset();
private:
@ -227,6 +228,7 @@ public:
void setDefaultArgument(Argument *argument);
void checkConstraints();
void invokeCallbacks();
bool isUncombinableMainArgPresent() const;
private:
IF_DEBUG_BUILD(void verifyArgs(const ArgumentVector &args);)