Base::Exception extension
========================= 1. Enable automatic storing of information (function, file, line) when throwing the exception via macro: Examples: THROWM(Exception, "BSpline GeoId is out of bounds.") THROWM(ValueError, "BSpline GeoId is out of bounds.") THROW(AbortException) Output: a) Python Console (what()): App.ActiveDocument.Sketch004.modifyBSplineKnotMultiplicity(16,3,0) Traceback (most recent call last): File "<input>", line 1, in <module> Base.FreeCADError: FreeCAD exception thrown (BSpline GeoId is out of bounds.) b) ReportException (report()): Exception (Thu Apr 27 19:15:24 2017): BSpline GeoId is out of bounds. in bool Sketcher::SketchObject::modifyBSplineKnotMultiplicity(int, int, int) in src/Mod/Sketcher/App/SketchObject.cpp:4102 2. Extend the basic framework so as to allow more control over the mangling of the message introduced by the user, setting the basis to allow, where needed, to preserve the original message while allowing full legacy behaviour. 3. Supporting FileDialog reporting as legacy
This commit is contained in:
@@ -41,7 +41,7 @@ Exception::Exception(void)
|
||||
}
|
||||
|
||||
Exception::Exception(const Exception &inst)
|
||||
: BaseClass(),_sErrMsg(inst._sErrMsg)
|
||||
: BaseClass(),_sErrMsg(inst._sErrMsg), _file(inst._file), _line(inst._line), _function(inst._function)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -69,7 +69,30 @@ const char* Exception::what(void) const throw()
|
||||
|
||||
void Exception::ReportException (void) const
|
||||
{
|
||||
Console().Error("Exception (%s): %s \n",Console().Time(),what());
|
||||
std::string str = "";
|
||||
|
||||
if(!_sErrMsg.empty())
|
||||
str+= (_sErrMsg + " ");
|
||||
|
||||
if(!_function.empty()) {
|
||||
str+="In ";
|
||||
str+=_function;
|
||||
str+= " ";
|
||||
}
|
||||
|
||||
if(!_file.empty() && !_line.empty()) {
|
||||
// strip absolute path
|
||||
std::size_t pos = _file.find("src");
|
||||
|
||||
if (pos!=std::string::npos) {
|
||||
str+="in ";
|
||||
str+= _file.substr(pos);
|
||||
str+= ":";
|
||||
str+=_line;
|
||||
}
|
||||
}
|
||||
|
||||
Console().Error("Exception (%s): %s \n",Console().Time(),str.c_str());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
@@ -144,33 +167,68 @@ FileException::FileException(const char * sMessage, const char * sFileName)
|
||||
: Exception( sMessage ),file(sFileName)
|
||||
{
|
||||
if (sFileName) {
|
||||
_sErrMsg += ": ";
|
||||
_sErrMsg += sFileName;
|
||||
_sErrMsgAndFileName = _sErrMsg + ": ";
|
||||
_sErrMsgAndFileName += sFileName;
|
||||
}
|
||||
}
|
||||
|
||||
FileException::FileException(const char * sMessage, const FileInfo& File)
|
||||
: Exception( sMessage ),file(File)
|
||||
{
|
||||
_sErrMsg += ": ";
|
||||
_sErrMsg += File.fileName();
|
||||
_sErrMsgAndFileName = _sErrMsg + ": ";
|
||||
_sErrMsgAndFileName += File.fileName();
|
||||
}
|
||||
|
||||
FileException::FileException()
|
||||
: Exception( "Unknown file exeption happened" )
|
||||
: Exception( "Unknown file exception happened" )
|
||||
{
|
||||
_sErrMsgAndFileName = _sErrMsg;
|
||||
}
|
||||
|
||||
FileException::FileException(const FileException &inst)
|
||||
: Exception( inst._sErrMsg.c_str() ),file(inst.file)
|
||||
: Exception( inst._sErrMsg.c_str() ), file(inst.file), _sErrMsgAndFileName(inst._sErrMsgAndFileName.c_str())
|
||||
{
|
||||
}
|
||||
|
||||
std::string FileException::getFileName() const
|
||||
{
|
||||
return file.fileName();
|
||||
}
|
||||
|
||||
const char* FileException::what() const throw()
|
||||
{
|
||||
return Exception::what();
|
||||
return _sErrMsgAndFileName.c_str();
|
||||
}
|
||||
|
||||
void FileException::ReportException (void) const
|
||||
{
|
||||
std::string str = "";
|
||||
|
||||
if(!_sErrMsgAndFileName.empty())
|
||||
str+= (_sErrMsgAndFileName + " ");
|
||||
|
||||
if(!_function.empty()) {
|
||||
str+="In ";
|
||||
str+=_function;
|
||||
str+= " ";
|
||||
}
|
||||
|
||||
if(!_file.empty() && !_line.empty()) {
|
||||
// strip absolute path
|
||||
std::size_t pos = _file.find("src");
|
||||
|
||||
if (pos!=std::string::npos) {
|
||||
str+="in ";
|
||||
str+= _file.substr(pos);
|
||||
str+= ":";
|
||||
str+=_line;
|
||||
}
|
||||
}
|
||||
|
||||
Console().Error("Exception (%s): %s \n",Console().Time(),str.c_str());
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
FileSystemError::FileSystemError(const char * sMessage)
|
||||
@@ -562,6 +620,7 @@ CADKernelError::CADKernelError(const CADKernelError &inst)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
#if defined(__GNUC__) && defined (FC_OS_LINUX)
|
||||
|
||||
@@ -33,6 +33,13 @@
|
||||
#include "FileInfo.h"
|
||||
#include "BaseClass.h"
|
||||
|
||||
/* MACROS FOR THROWING EXCEPTIONS */
|
||||
|
||||
#define THROW(exception) {exception myexcp; myexcp.setDebugInformation(__FILE__,__LINE__,__PRETTY_FUNCTION__); throw myexcp;}
|
||||
#define THROWM(exception, message) {exception myexcp(message); myexcp.setDebugInformation(__FILE__,__LINE__,__PRETTY_FUNCTION__); throw myexcp;}
|
||||
|
||||
#define THROWMF_FILEEXCEPTION(message,filenameorfileinfo) {FileException myexcp(message, filenameorfileinfo); myexcp.setDebugInformation(__FILE__,__LINE__,__PRETTY_FUNCTION__); throw myexcp;}
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
@@ -41,16 +48,32 @@ class BaseExport Exception : public BaseClass
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Exception() throw() {}
|
||||
|
||||
Exception &operator=(const Exception &inst);
|
||||
|
||||
virtual const char* what(void) const throw();
|
||||
|
||||
virtual void ReportException (void) const;
|
||||
|
||||
inline void setMessage(const char * sMessage);
|
||||
inline void setMessage(const std::string& sMessage);
|
||||
// what may differ from the message given by the user in
|
||||
// derived classes
|
||||
inline std::string getMessage() const;
|
||||
|
||||
/// setter methods for including debug information
|
||||
/// intended to use via macro for autofilling of debugging information
|
||||
inline void setDebugInformation(const std::string & file, const int line, const std::string & function);
|
||||
|
||||
protected:
|
||||
public: // FIXME: Remove the public keyword
|
||||
/* sMessage may be:
|
||||
* - an UI compliant string subsceptible of being translated and shown to the user in the UI
|
||||
* - a very technical message not intended to be traslated or shown to the user in the UI
|
||||
* The preferred way of throwing an exception is using the macros above. This way, the file,
|
||||
* line and function are automatically inserted. */
|
||||
Exception(const char * sMessage);
|
||||
Exception(const std::string& sMessage);
|
||||
Exception(void);
|
||||
@@ -58,6 +81,9 @@ public: // FIXME: Remove the public keyword
|
||||
|
||||
protected:
|
||||
std::string _sErrMsg;
|
||||
std::string _file;
|
||||
std::string _line;
|
||||
std::string _function;
|
||||
};
|
||||
|
||||
|
||||
@@ -74,6 +100,7 @@ public:
|
||||
AbortException();
|
||||
/// Construction
|
||||
AbortException(const AbortException &inst);
|
||||
|
||||
/// Destruction
|
||||
virtual ~AbortException() throw() {}
|
||||
/// Description of the exception
|
||||
@@ -92,6 +119,7 @@ public:
|
||||
XMLBaseException(const std::string& sMessage);
|
||||
/// Construction
|
||||
XMLBaseException(const XMLBaseException &inst);
|
||||
|
||||
/// Destruction
|
||||
virtual ~XMLBaseException() throw() {}
|
||||
};
|
||||
@@ -111,6 +139,7 @@ public:
|
||||
XMLParseException();
|
||||
/// Construction
|
||||
XMLParseException(const XMLParseException &inst);
|
||||
|
||||
/// Destruction
|
||||
virtual ~XMLParseException() throw() {}
|
||||
/// Description of the exception
|
||||
@@ -136,8 +165,14 @@ public:
|
||||
virtual ~FileException() throw() {}
|
||||
/// Description of the exception
|
||||
virtual const char* what() const throw();
|
||||
/// Report generation
|
||||
virtual void ReportException (void) const;
|
||||
/// Get file name for use with tranlatable message
|
||||
std::string getFileName() const;
|
||||
protected:
|
||||
FileInfo file;
|
||||
// necesary for what() legacy behaviour as it returns a buffer that can not be of a temporary object to be destroyed at end of what()
|
||||
std::string _sErrMsgAndFileName;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -259,6 +294,7 @@ public:
|
||||
ProgramInformation(const std::string& sMessage);
|
||||
/// Construction
|
||||
ProgramInformation(const ProgramInformation &inst);
|
||||
|
||||
/// Destruction
|
||||
virtual ~ProgramInformation() throw() {}
|
||||
};
|
||||
@@ -516,6 +552,18 @@ inline void Exception::setMessage(const std::string& sMessage)
|
||||
_sErrMsg = sMessage;
|
||||
}
|
||||
|
||||
inline std::string Exception::getMessage() const
|
||||
{
|
||||
return _sErrMsg;
|
||||
}
|
||||
|
||||
inline void Exception::setDebugInformation(const std::string & file, const int line, const std::string & function)
|
||||
{
|
||||
_file = file;
|
||||
_line = std::to_string(line);
|
||||
_function = function;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && defined (FC_OS_LINUX)
|
||||
class SignalException
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user