1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-16 05:26:58 +08:00

cmFunctionBlocker: Move check for matching args

This commit is contained in:
Regina Pfeifer
2019-07-30 22:58:40 +02:00
parent af24e4ef6e
commit 6491270e0d
9 changed files with 65 additions and 100 deletions

View File

@@ -28,7 +28,9 @@ public:
cm::string_view StartCommandName() const override { return "foreach"_s; } cm::string_view StartCommandName() const override { return "foreach"_s; }
cm::string_view EndCommandName() const override { return "endforeach"_s; } cm::string_view EndCommandName() const override { return "endforeach"_s; }
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override; bool ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) const override;
bool Replay(std::vector<cmListFileFunction> const& functions, bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& inStatus) override; cmExecutionStatus& inStatus) override;
@@ -49,20 +51,12 @@ cmForEachFunctionBlocker::~cmForEachFunctionBlocker()
this->Makefile->PopLoopBlock(); this->Makefile->PopLoopBlock();
} }
bool cmForEachFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, bool cmForEachFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) cmMakefile& mf) const
{ {
if (lff.Name.Lower == "endforeach") {
std::vector<std::string> expandedArguments; std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments); mf.ExpandArguments(lff.Arguments, expandedArguments);
// if the endforeach has arguments then make sure return expandedArguments.empty() || expandedArguments[0] == this->Args[0];
// they match the begin foreach arguments
if ((expandedArguments.empty() ||
(expandedArguments[0] == this->Args[0]))) {
return true;
}
}
return false;
} }
bool cmForEachFunctionBlocker::Replay( bool cmForEachFunctionBlocker::Replay(

View File

@@ -2,8 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFunctionBlocker.h" #include "cmFunctionBlocker.h"
#include <cassert>
#include <sstream>
#include "cmExecutionStatus.h" #include "cmExecutionStatus.h"
#include "cmMakefile.h" #include "cmMakefile.h"
#include "cmMessageType.h"
bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
cmExecutionStatus& status) cmExecutionStatus& status)
@@ -14,7 +18,24 @@ bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
this->ScopeDepth--; this->ScopeDepth--;
if (this->ScopeDepth == 0U) { if (this->ScopeDepth == 0U) {
cmMakefile& mf = status.GetMakefile(); cmMakefile& mf = status.GetMakefile();
auto self = mf.RemoveFunctionBlocker(this, lff); auto self = mf.RemoveFunctionBlocker();
assert(self.get() == this);
if (!this->ArgumentsMatch(lff, mf)) {
cmListFileContext const& lfc = this->GetStartingContext();
cmListFileContext closingContext =
cmListFileContext::FromCommandContext(lff, lfc.FilePath);
std::ostringstream e;
/* clang-format off */
e << "A logical block opening on the line\n"
<< " " << lfc << "\n"
<< "closes on the line\n"
<< " " << closingContext << "\n"
<< "with mis-matching arguments.";
/* clang-format on */
mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
return this->Replay(this->Functions, status); return this->Replay(this->Functions, status);
} }
} }

View File

@@ -23,15 +23,6 @@ public:
bool IsFunctionBlocked(cmListFileFunction const& lff, bool IsFunctionBlocked(cmListFileFunction const& lff,
cmExecutionStatus& status); cmExecutionStatus& status);
/**
* should this function blocker be removed, useful when one function adds a
* blocker and another must remove it
*/
virtual bool ShouldRemove(const cmListFileFunction&, cmMakefile&)
{
return false;
}
virtual ~cmFunctionBlocker() = default; virtual ~cmFunctionBlocker() = default;
/** Set/Get the context in which this blocker is created. */ /** Set/Get the context in which this blocker is created. */
@@ -48,6 +39,9 @@ private:
virtual cm::string_view StartCommandName() const = 0; virtual cm::string_view StartCommandName() const = 0;
virtual cm::string_view EndCommandName() const = 0; virtual cm::string_view EndCommandName() const = 0;
virtual bool ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) const = 0;
virtual bool Replay(std::vector<cmListFileFunction> const& functions, virtual bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& status) = 0; cmExecutionStatus& status) = 0;

View File

@@ -113,29 +113,22 @@ public:
cm::string_view StartCommandName() const override { return "function"_s; } cm::string_view StartCommandName() const override { return "function"_s; }
cm::string_view EndCommandName() const override { return "endfunction"_s; } cm::string_view EndCommandName() const override { return "endfunction"_s; }
bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override; bool ArgumentsMatch(cmListFileFunction const&,
cmMakefile& mf) const override;
bool Replay(std::vector<cmListFileFunction> const& functions, bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& status) override; cmExecutionStatus& status) override;
std::vector<std::string> Args; std::vector<std::string> Args;
}; };
bool cmFunctionFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, bool cmFunctionFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) cmMakefile& mf) const
{ {
if (lff.Name.Lower == "endfunction") {
std::vector<std::string> expandedArguments; std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments, mf.ExpandArguments(lff.Arguments, expandedArguments,
this->GetStartingContext().FilePath.c_str()); this->GetStartingContext().FilePath.c_str());
// if the endfunction has arguments then make sure return expandedArguments.empty() || expandedArguments[0] == this->Args[0];
// they match the ones in the opening function command
if ((expandedArguments.empty() ||
(expandedArguments[0] == this->Args[0]))) {
return true;
}
}
return false;
} }
bool cmFunctionFunctionBlocker::Replay( bool cmFunctionFunctionBlocker::Replay(

View File

@@ -38,7 +38,9 @@ public:
cm::string_view StartCommandName() const override { return "if"_s; } cm::string_view StartCommandName() const override { return "if"_s; }
cm::string_view EndCommandName() const override { return "endif"_s; } cm::string_view EndCommandName() const override { return "endif"_s; }
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override; bool ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile&) const override;
bool Replay(std::vector<cmListFileFunction> const& functions, bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& inStatus) override; cmExecutionStatus& inStatus) override;
@@ -48,18 +50,10 @@ public:
bool ElseSeen = false; bool ElseSeen = false;
}; };
bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, bool cmIfFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile&) cmMakefile&) const
{ {
if (lff.Name.Lower == "endif") { return lff.Arguments.empty() || lff.Arguments == this->Args;
// if the endif has arguments, then make sure
// they match the arguments of the matching if
if (lff.Arguments.empty() || lff.Arguments == this->Args) {
return true;
}
}
return false;
} }
bool cmIfFunctionBlocker::Replay( bool cmIfFunctionBlocker::Replay(

View File

@@ -146,29 +146,22 @@ public:
cm::string_view StartCommandName() const override { return "macro"_s; } cm::string_view StartCommandName() const override { return "macro"_s; }
cm::string_view EndCommandName() const override { return "endmacro"_s; } cm::string_view EndCommandName() const override { return "endmacro"_s; }
bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override; bool ArgumentsMatch(cmListFileFunction const&,
cmMakefile& mf) const override;
bool Replay(std::vector<cmListFileFunction> const& functions, bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& status) override; cmExecutionStatus& status) override;
std::vector<std::string> Args; std::vector<std::string> Args;
}; };
bool cmMacroFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, bool cmMacroFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) cmMakefile& mf) const
{ {
if (lff.Name.Lower == "endmacro") {
std::vector<std::string> expandedArguments; std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments, mf.ExpandArguments(lff.Arguments, expandedArguments,
this->GetStartingContext().FilePath.c_str()); this->GetStartingContext().FilePath.c_str());
// if the endmacro has arguments make sure they return expandedArguments.empty() || expandedArguments[0] == this->Args[0];
// match the arguments of the macro
if ((expandedArguments.empty() ||
(expandedArguments[0] == this->Args[0]))) {
return true;
}
}
return false;
} }
bool cmMacroFunctionBlocker::Replay( bool cmMacroFunctionBlocker::Replay(

View File

@@ -3220,30 +3220,12 @@ void cmMakefile::AddFunctionBlocker(std::unique_ptr<cmFunctionBlocker> fb)
this->FunctionBlockers.push(std::move(fb)); this->FunctionBlockers.push(std::move(fb));
} }
std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker( std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker()
cmFunctionBlocker* fb, const cmListFileFunction& lff)
{ {
assert(!this->FunctionBlockers.empty()); assert(!this->FunctionBlockers.empty());
assert(this->FunctionBlockers.top().get() == fb);
assert(this->FunctionBlockerBarriers.empty() || assert(this->FunctionBlockerBarriers.empty() ||
this->FunctionBlockers.size() > this->FunctionBlockerBarriers.back()); this->FunctionBlockers.size() > this->FunctionBlockerBarriers.back());
// Warn if the arguments do not match, but always remove.
if (!fb->ShouldRemove(lff, *this)) {
cmListFileContext const& lfc = fb->GetStartingContext();
cmListFileContext closingContext =
cmListFileContext::FromCommandContext(lff, lfc.FilePath);
std::ostringstream e;
/* clang-format off */
e << "A logical block opening on the line\n"
<< " " << lfc << "\n"
<< "closes on the line\n"
<< " " << closingContext << "\n"
<< "with mis-matching arguments.";
/* clang-format on */
this->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
auto b = std::move(this->FunctionBlockers.top()); auto b = std::move(this->FunctionBlockers.top());
this->FunctionBlockers.pop(); this->FunctionBlockers.pop();
return b; return b;

View File

@@ -107,8 +107,7 @@ public:
* Remove the function blocker whose scope ends with the given command. * Remove the function blocker whose scope ends with the given command.
* This returns ownership of the function blocker object. * This returns ownership of the function blocker object.
*/ */
std::unique_ptr<cmFunctionBlocker> RemoveFunctionBlocker( std::unique_ptr<cmFunctionBlocker> RemoveFunctionBlocker();
cmFunctionBlocker* fb, const cmListFileFunction& lff);
/** /**
* Try running cmake and building a file. This is used for dynalically * Try running cmake and building a file. This is used for dynalically

View File

@@ -27,7 +27,9 @@ public:
cm::string_view StartCommandName() const override { return "while"_s; } cm::string_view StartCommandName() const override { return "while"_s; }
cm::string_view EndCommandName() const override { return "endwhile"_s; } cm::string_view EndCommandName() const override { return "endwhile"_s; }
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override; bool ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) const override;
bool Replay(std::vector<cmListFileFunction> const& functions, bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& inStatus) override; cmExecutionStatus& inStatus) override;
@@ -48,17 +50,10 @@ cmWhileFunctionBlocker::~cmWhileFunctionBlocker()
this->Makefile->PopLoopBlock(); this->Makefile->PopLoopBlock();
} }
bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, bool cmWhileFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile&) cmMakefile&) const
{ {
if (lff.Name.Lower == "endwhile") { return lff.Arguments.empty() || lff.Arguments == this->Args;
// if the endwhile has arguments, then make sure
// they match the arguments of the matching while
if (lff.Arguments.empty() || lff.Arguments == this->Args) {
return true;
}
}
return false;
} }
bool cmWhileFunctionBlocker::Replay( bool cmWhileFunctionBlocker::Replay(