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:
Abdullah Tahiri
2017-04-28 22:39:56 +02:00
committed by wmayer
parent c974e9d752
commit 1091511c77
2 changed files with 116 additions and 9 deletions

View File

@@ -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)

View File

@@ -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
{