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. * If the argument is in conflict with an other argument this argument will be returned.
* Otherwise nullptr will be returned. * Otherwise nullptr will be returned.
*
* \remarks Conflicts with main arguments aren't considered by this method!
*/ */
Argument *Argument::conflictsWithArgument() const 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 *parent : m_parents) {
for(Argument *sibling : parent->subArguments()) { for(Argument *sibling : parent->subArguments()) {
if(sibling != this && sibling->isPresent() && !sibling->isCombinable()) { 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 #ifdef DEBUG_BUILD
/*! /*!
* \brief Verifies the specified \a argument definitions. * \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 // use the first default argument which is not already present if there is still no match
if(!matchingArg && (!completionMode || (argv + 1 != end))) { if(!matchingArg && (!completionMode || (argv + 1 != end))) {
const bool uncombinableMainArgPresent = parentArg ? false : isUncombinableMainArgPresent();
for(Argument *arg : args) { 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); (matchingArg = arg)->m_occurrences.emplace_back(index, parentPath, parentArg);
break; break;
} }

View File

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