// // ScriptException.h // libraries/script-engine/src // // Created by Dale Glass on 27/02/2023. // Copyright 2023 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html #include #include #include #include "ScriptValue.h" #pragma once /** * @brief Scripting exception * * Emitted from the scripting engine when an exception happens inside it. * This is the base class. * */ class ScriptException { public: ScriptException(QString message = "", QString info = "", int line = 0, int column = 0, QStringList backtraceList = QStringList()) : errorMessage(message), additionalInfo(info), errorLine(line), errorColumn(column), backtrace(backtraceList) { } /** * @brief Error message * */ QString errorMessage; /** * @brief Additional information about the exception * * This is additional information added at the place where the exception happened. * It may contain information about what the system was doing when the exception happened. * */ QString additionalInfo; /** * @brief Error line * */ int errorLine; /** * @brief Error column * */ int errorColumn; /** * @brief Backtrace * */ QStringList backtrace; bool isEmpty() const { return errorMessage.isEmpty(); } /** * @brief Clones this object. * * This is used in the scripting engine to ensure that while it can return different * exception objects depending on what happened, the returned object is a copy that * doesn't allow the caller to accidentally break the ScriptEngine's internal state. * * @return std::shared_ptr */ virtual std::shared_ptr clone() const { return std::make_shared(*this); } }; /** * @brief Exception that ocurred inside the scripting engine on the c++ side * * This is something that went wrong inside the ScriptEngine or ScriptManager * infrastructure. * */ class ScriptEngineException : public ScriptException { public: ScriptEngineException(QString message = "", QString info = "", int line = 0, int column = 0, QStringList backtraceList = QStringList()) : ScriptException(message, info, line, column, backtraceList) { } /** * @brief Clones this object. * * This is used in the scripting engine to ensure that while it can return different * exception objects depending on what happened, the returned object is a copy that * doesn't allow the caller to accidentally break the ScriptEngine's internal state. * * @return std::shared_ptr */ virtual std::shared_ptr clone() const override { return std::make_shared(*this); } }; /** * @brief Exception that ocurred inside the running script * * This is something that went wrong inside the running script. * */ class ScriptRuntimeException : public ScriptException { public: ScriptRuntimeException(QString message = "", QString info = "", int line = 0, int column = 0, QStringList backtraceList = QStringList()) : ScriptException(message, info, line, column, backtraceList) { } /** * @brief The actual value that was thrown by the script. * * The content is completely arbitrary. * */ ScriptValue thrownValue; /** * @brief Clones this object. * * This is used in the scripting engine to ensure that while it can return different * exception objects depending on what happened, the returned object is a copy that * doesn't allow the caller to accidentally break the ScriptEngine's internal state. * * @return std::shared_ptr */ virtual std::shared_ptr clone() const override { return std::make_shared(*this); } }; inline QDebug operator<<(QDebug debug, const ScriptException& e) { debug << "Exception:" << e.errorMessage << (e.additionalInfo.isEmpty() ? QString("") : "[" + e.additionalInfo + "]") << " at line " << e.errorLine << ", column " << e.errorColumn; if (e.backtrace.length()) { debug << "Backtrace:"; debug << e.backtrace; } return debug; } // Is this a bad practice? inline QDebug operator<<(QDebug debug, std::shared_ptr e) { if (!e) { debug << "[Null ScriptException]"; return debug; } debug << *e.get(); return debug; } Q_DECLARE_METATYPE(ScriptException) Q_DECLARE_METATYPE(ScriptEngineException) Q_DECLARE_METATYPE(ScriptRuntimeException) Q_DECLARE_METATYPE(std::shared_ptr) Q_DECLARE_METATYPE(std::shared_ptr) Q_DECLARE_METATYPE(std::shared_ptr)