From e17af4231a9e16eb554a7b2fa56d3ca18fb99ead Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 14 Feb 2014 13:38:30 +0100 Subject: [PATCH] added script verifier --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/tools/scriptcheck.cpp | 98 +++++++++++++++++++++++ apps/opencs/model/tools/scriptcheck.hpp | 40 +++++++++ apps/opencs/model/tools/tools.cpp | 3 + apps/opencs/model/world/scriptcontext.cpp | 9 ++- apps/opencs/model/world/scriptcontext.hpp | 3 + 6 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 apps/opencs/model/tools/scriptcheck.cpp create mode 100644 apps/opencs/model/tools/scriptcheck.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 5c3cd0dcc..82313b7ed 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -38,7 +38,7 @@ opencs_units (model/tools opencs_units_noqt (model/tools mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck - birthsigncheck spellcheck referenceablecheck + birthsigncheck spellcheck referenceablecheck scriptcheck ) diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp new file mode 100644 index 000000000..8ed41ec02 --- /dev/null +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -0,0 +1,98 @@ + +#include "scriptcheck.hpp" + +#include +#include +#include +#include +#include + +#include "../world/data.hpp" + +void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc, + Type type) +{ + std::ostringstream stream; + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); + + stream << id.toString() << "|"; + + if (type==ErrorMessage) + stream << "error "; + else + stream << "warning "; + + stream + << "line " << loc.mLine << ", column " << loc.mColumn + << " (" << loc.mLiteral << "): " << message; + + mMessages->push_back (stream.str()); +} + +void CSMTools::ScriptCheckStage::report (const std::string& message, Type type) +{ + std::ostringstream stream; + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); + + stream << id.toString() << "|"; + + if (type==ErrorMessage) + stream << "error: "; + else + stream << "warning: "; + + stream << message; + + mMessages->push_back (stream.str()); +} + +CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMWorld::Data& data) +: mData (data), mContext (data), mMessages (0) +{ + Compiler::registerExtensions (mExtensions); + mContext.setExtensions (&mExtensions); +} + +int CSMTools::ScriptCheckStage::setup() +{ + mContext.clear(); + mMessages = 0; + mId.clear(); + + return mData.getScripts().getSize(); +} + +void CSMTools::ScriptCheckStage::perform (int stage, std::vector& messages) +{ + mMessages = &messages; + mId = mData.getScripts().getId (stage); + + try + { + std::istringstream input (mData.getScripts().getRecord (stage).get().mScriptText); + + Compiler::Scanner scanner (*this, input, mContext.getExtensions()); + + Compiler::FileParser parser (*this, mContext); + + scanner.scan (parser); + } + catch (const Compiler::SourceException&) + { + // error has already been reported via error handler + } + catch (const std::exception& error) + { + std::ostringstream stream; + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); + + stream << id.toString() << "|Critical compile error: " << error.what(); + + messages.push_back (stream.str()); + } + + mMessages = 0; +} \ No newline at end of file diff --git a/apps/opencs/model/tools/scriptcheck.hpp b/apps/opencs/model/tools/scriptcheck.hpp new file mode 100644 index 000000000..325280d7f --- /dev/null +++ b/apps/opencs/model/tools/scriptcheck.hpp @@ -0,0 +1,40 @@ +#ifndef CSM_TOOLS_SCRIPTCHECK_H +#define CSM_TOOLS_SCRIPTCHECK_H + +#include +#include + +#include "../doc/stage.hpp" + +#include "../world/scriptcontext.hpp" + +namespace CSMTools +{ + /// \brief VerifyStage: make sure that scripts compile + class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler + { + const CSMWorld::Data& mData; + Compiler::Extensions mExtensions; + CSMWorld::ScriptContext mContext; + std::string mId; + std::vector *mMessages; + + virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type); + ///< Report error to the user. + + virtual void report (const std::string& message, Type type); + ///< Report a file related error + + public: + + ScriptCheckStage (const CSMWorld::Data& data); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, std::vector& messages); + ///< Messages resulting from this tage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 64e39ad2f..79a09dcb4 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -20,6 +20,7 @@ #include "birthsigncheck.hpp" #include "spellcheck.hpp" #include "referenceablecheck.hpp" +#include "scriptcheck.hpp" CSMDoc::Operation *CSMTools::Tools::get (int type) { @@ -77,6 +78,8 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier() mVerifier->appendStage (new SpellCheckStage (mData.getSpells())); mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions())); + + mVerifier->appendStage (new ScriptCheckStage (mData)); } return mVerifier; diff --git a/apps/opencs/model/world/scriptcontext.cpp b/apps/opencs/model/world/scriptcontext.cpp index 688c33d30..8a4670ed2 100644 --- a/apps/opencs/model/world/scriptcontext.cpp +++ b/apps/opencs/model/world/scriptcontext.cpp @@ -15,7 +15,7 @@ CSMWorld::ScriptContext::ScriptContext (const Data& data) : mData (data), mIdsUp bool CSMWorld::ScriptContext::canDeclareLocals() const { - return false; + return true; } char CSMWorld::ScriptContext::getGlobalType (const std::string& name) const @@ -115,4 +115,11 @@ bool CSMWorld::ScriptContext::isJournalId (const std::string& name) const void CSMWorld::ScriptContext::invalidateIds() { mIdsUpdated = false; +} + +void CSMWorld::ScriptContext::clear() +{ + mIds.clear(); + mIdsUpdated = false; + mLocals.clear(); } \ No newline at end of file diff --git a/apps/opencs/model/world/scriptcontext.hpp b/apps/opencs/model/world/scriptcontext.hpp index 400748e5f..29ee42645 100644 --- a/apps/opencs/model/world/scriptcontext.hpp +++ b/apps/opencs/model/world/scriptcontext.hpp @@ -43,6 +43,9 @@ namespace CSMWorld ///< Does \a name match a journal ID? void invalidateIds(); + + void clear(); + ///< Remove all cached data. }; }