ENH: Better error message for unclosed blocks

This centralizes construction of the error message for an unclosed
logical block (if, foreach, etc.).  We record the line at which each
block is opened so it can be reported in the error message.
This commit is contained in:
Brad King 2009-01-21 09:48:20 -05:00
parent b8f5a934ec
commit bca1026250
13 changed files with 30 additions and 73 deletions

View File

@ -107,15 +107,6 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf)
return false;
}
void cmForEachFunctionBlocker::
ScopeEnded(cmMakefile &mf)
{
cmSystemTools::Error("The end of a CMakeLists file was reached with a "
"FOREACH statement that was not closed properly. "
"Within the directory: ",
mf.GetCurrentDirectory());
}
bool cmForEachCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{

View File

@ -35,7 +35,6 @@ public:
cmMakefile &mf,
cmExecutionStatus &);
virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf);
virtual void ScopeEnded(cmMakefile &mf);
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;

View File

@ -19,6 +19,7 @@
#include "cmStandardIncludes.h"
#include "cmExecutionStatus.h"
#include "cmListFileCache.h"
class cmMakefile;
/** \class cmFunctionBlocker
@ -43,14 +44,15 @@ public:
virtual bool ShouldRemove(const cmListFileFunction&,
cmMakefile&) {return false;}
/**
* When the end of a CMakeList file is reached this method is called. It
* is not called on the end of an INCLUDE cmake file, just at the end of a
* regular CMakeList file
*/
virtual void ScopeEnded(cmMakefile&) {}
virtual ~cmFunctionBlocker() {}
/** Set/Get the context in which this blocker is created. */
void SetStartingContext(cmListFileContext const& lfc)
{ this->StartingContext = lfc; }
cmListFileContext const& GetStartingContext()
{ return this->StartingContext; }
private:
cmListFileContext StartingContext;
};
#endif

View File

@ -258,17 +258,6 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf)
return false;
}
void cmFunctionFunctionBlocker::
ScopeEnded(cmMakefile &mf)
{
// functions should end with an EndFunction
cmSystemTools::Error(
"The end of a CMakeLists file was reached with a FUNCTION statement that "
"was not closed properly. Within the directory: ",
mf.GetCurrentDirectory(), " with function ",
this->Args[0].c_str());
}
bool cmFunctionCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{

View File

@ -34,7 +34,6 @@ public:
cmMakefile &mf,
cmExecutionStatus &);
virtual bool ShouldRemove(const cmListFileFunction&, cmMakefile &mf);
virtual void ScopeEnded(cmMakefile &mf);
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;

View File

@ -157,24 +157,6 @@ bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
return false;
}
//=========================================================================
void cmIfFunctionBlocker::ScopeEnded(cmMakefile &mf)
{
std::string errmsg = "The end of a CMakeLists file was reached with an "
"IF statement that was not closed properly.\nWithin the directory: ";
errmsg += mf.GetCurrentDirectory();
errmsg += "\nThe arguments are: ";
for(std::vector<cmListFileArgument>::const_iterator j = this->Args.begin();
j != this->Args.end(); ++j)
{
errmsg += (j->Quoted?"\"":"");
errmsg += j->Value;
errmsg += (j->Quoted?"\"":"");
errmsg += " ";
}
cmSystemTools::Message(errmsg.c_str(), "Warning");
}
//=========================================================================
bool cmIfCommand
::InvokeInitialPass(const std::vector<cmListFileArgument>& args,

View File

@ -36,7 +36,6 @@ public:
cmExecutionStatus &);
virtual bool ShouldRemove(const cmListFileFunction& lff,
cmMakefile &mf);
virtual void ScopeEnded(cmMakefile &mf);
std::vector<cmListFileArgument> Args;
std::vector<cmListFileFunction> Functions;

View File

@ -302,17 +302,6 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf)
return false;
}
void cmMacroFunctionBlocker::
ScopeEnded(cmMakefile &mf)
{
// macros should end with an EndMacro
cmSystemTools::Error(
"The end of a CMakeLists file was reached with a MACRO statement that "
"was not closed properly. Within the directory: ",
mf.GetCurrentDirectory(), " with macro ",
this->Args[0].c_str());
}
bool cmMacroCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus &)
{

View File

@ -34,7 +34,6 @@ public:
cmMakefile &mf,
cmExecutionStatus &);
virtual bool ShouldRemove(const cmListFileFunction&, cmMakefile &mf);
virtual void ScopeEnded(cmMakefile &mf);
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;

View File

@ -2365,7 +2365,14 @@ void cmMakefile::PopFunctionBlockerBarrier(bool reportError)
this->FunctionBlockers.pop_back();
if(reportError)
{
fb->ScopeEnded(*this);
// Report the context in which the unclosed block was opened.
cmListFileContext const& lfc = fb->GetStartingContext();
cmOStringStream e;
e << "A logical block opening on the line\n"
<< " " << lfc << "\n"
<< "is not closed.";
this->IssueMessage(cmake::FATAL_ERROR, e.str());
reportError = false;
}
}
@ -2402,6 +2409,18 @@ bool cmMakefile::ExpandArguments(
return !cmSystemTools::GetFatalErrorOccured();
}
//----------------------------------------------------------------------------
void cmMakefile::AddFunctionBlocker(cmFunctionBlocker* fb)
{
if(!this->CallStack.empty())
{
// Record the context in which the blocker is created.
fb->SetStartingContext(*(this->CallStack.back().Context));
}
this->FunctionBlockers.push_back(fb);
}
cmsys::auto_ptr<cmFunctionBlocker>
cmMakefile::RemoveFunctionBlocker(const cmListFileFunction& lff)
{

View File

@ -88,8 +88,7 @@ public:
/**
* Add a function blocker to this makefile
*/
void AddFunctionBlocker(cmFunctionBlocker *fb)
{ this->FunctionBlockers.push_back(fb);}
void AddFunctionBlocker(cmFunctionBlocker* fb);
/**
* Remove the function blocker whose scope ends with the given command.

View File

@ -97,15 +97,6 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile& )
return false;
}
void cmWhileFunctionBlocker::
ScopeEnded(cmMakefile &mf)
{
cmSystemTools::Error(
"The end of a CMakeLists file was reached with a WHILE statement that "
"was not closed properly. Within the directory: ",
mf.GetCurrentDirectory());
}
bool cmWhileCommand
::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
cmExecutionStatus &)

View File

@ -35,7 +35,6 @@ public:
cmMakefile &mf,
cmExecutionStatus &);
virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf);
virtual void ScopeEnded(cmMakefile &mf);
std::vector<cmListFileArgument> Args;
std::vector<cmListFileFunction> Functions;