mirror of
https://github.com/love2d/love.git
synced 2026-08-16 16:20:42 +02:00
Add the ability to have formally deprecated functions.
Functions which are deprecated will print out a message and show up in a small dialog on-screen, when they're first called. Deprecation output is disabled in fused mode by default, and can be modified with love.setDeprecationOutput(enable). --HG-- branch : minor
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
// LOVE
|
||||
#include "Module.h"
|
||||
#include "Exception.h"
|
||||
#include "deprecation.h"
|
||||
|
||||
// std
|
||||
#include <map>
|
||||
@@ -61,6 +62,11 @@ namespace love
|
||||
love::Type Module::type("Module", &Object::type);
|
||||
Module *Module::instances[] = {};
|
||||
|
||||
Module::Module()
|
||||
{
|
||||
initDeprecation();
|
||||
}
|
||||
|
||||
Module::~Module()
|
||||
{
|
||||
ModuleRegistry ®istry = registryInstance();
|
||||
@@ -83,6 +89,8 @@ Module::~Module()
|
||||
}
|
||||
|
||||
freeEmptyRegistry();
|
||||
|
||||
deinitDeprecation();
|
||||
}
|
||||
|
||||
void Module::registerInstance(Module *instance)
|
||||
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
M_MAX_ENUM
|
||||
};
|
||||
|
||||
Module();
|
||||
virtual ~Module();
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2017 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "common/config.h"
|
||||
#include "deprecation.h"
|
||||
#include "thread/threads.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
|
||||
namespace love
|
||||
{
|
||||
|
||||
static std::map<std::string, DeprecationInfo> deprecated;
|
||||
static std::vector<const DeprecationInfo *> deprecatedList;
|
||||
|
||||
static std::atomic<int> initCount;
|
||||
|
||||
static thread::Mutex *mutex = nullptr;
|
||||
static bool outputEnabled = false;
|
||||
|
||||
void initDeprecation()
|
||||
{
|
||||
if (initCount.fetch_add(1) == 0)
|
||||
mutex = thread::newMutex();
|
||||
}
|
||||
|
||||
void deinitDeprecation()
|
||||
{
|
||||
if (initCount.fetch_sub(1) == 1)
|
||||
{
|
||||
deprecatedList.clear();
|
||||
deprecated.clear();
|
||||
|
||||
delete mutex;
|
||||
mutex = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void printDeprecationNotice(const DeprecationInfo &info)
|
||||
{
|
||||
std::string notice = getDeprecationNotice(info, true);
|
||||
printf("LOVE - Warning: %s\n", notice.c_str());
|
||||
}
|
||||
|
||||
void setDeprecationOutputEnabled(bool enable)
|
||||
{
|
||||
if (enable == outputEnabled)
|
||||
return;
|
||||
|
||||
outputEnabled = enable;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
GetDeprecated deprecated;
|
||||
|
||||
for (const DeprecationInfo *info : deprecated.all)
|
||||
{
|
||||
if (info->uses == 1)
|
||||
printDeprecationNotice(*info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string getDeprecationNotice(const DeprecationInfo &info, bool usewhere)
|
||||
{
|
||||
std::string notice;
|
||||
|
||||
if (usewhere)
|
||||
notice += info.where;
|
||||
|
||||
notice += "Using deprecated function " + info.name;
|
||||
|
||||
if (info.type == DEPRECATED_REPLACEMENT && !info.replacement.empty())
|
||||
notice += " (replaced by " + info.replacement + ")";
|
||||
else if (info.type == DEPRECATED_RENAMED && !info.replacement.empty())
|
||||
notice += " (renamed to " + info.replacement + ")";
|
||||
|
||||
return notice;
|
||||
}
|
||||
|
||||
GetDeprecated::GetDeprecated()
|
||||
: all(deprecatedList)
|
||||
{
|
||||
if (mutex != nullptr)
|
||||
mutex->lock();
|
||||
}
|
||||
|
||||
GetDeprecated::~GetDeprecated()
|
||||
{
|
||||
if (mutex != nullptr)
|
||||
mutex->unlock();
|
||||
}
|
||||
|
||||
MarkDeprecated::MarkDeprecated(const char *name)
|
||||
: MarkDeprecated(name, DEPRECATED_NO_REPLACEMENT, nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
MarkDeprecated::MarkDeprecated(const char *name, DeprecationType type, const char *replacement)
|
||||
: info(nullptr)
|
||||
{
|
||||
if (mutex != nullptr)
|
||||
mutex->lock();
|
||||
|
||||
auto it = deprecated.find(name);
|
||||
|
||||
if (it != deprecated.end())
|
||||
{
|
||||
it->second.uses++;
|
||||
info = &it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
DeprecationInfo newinfo = {};
|
||||
|
||||
newinfo.type = type;
|
||||
newinfo.uses = 1;
|
||||
newinfo.name = name;
|
||||
|
||||
if (replacement != nullptr)
|
||||
newinfo.replacement = replacement;
|
||||
|
||||
auto inserted = deprecated.insert(std::make_pair(newinfo.name, newinfo));
|
||||
|
||||
info = &inserted.first->second;
|
||||
deprecatedList.push_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
MarkDeprecated::~MarkDeprecated()
|
||||
{
|
||||
if (outputEnabled && info != nullptr && info->uses == 1)
|
||||
printDeprecationNotice(*info);
|
||||
|
||||
if (mutex != nullptr)
|
||||
mutex->unlock();
|
||||
}
|
||||
|
||||
} // love
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2017 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "int.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace love
|
||||
{
|
||||
|
||||
enum DeprecationType
|
||||
{
|
||||
DEPRECATED_NO_REPLACEMENT,
|
||||
DEPRECATED_REPLACEMENT,
|
||||
DEPRECATED_RENAMED,
|
||||
};
|
||||
|
||||
struct DeprecationInfo
|
||||
{
|
||||
DeprecationType type;
|
||||
int64 uses;
|
||||
std::string name;
|
||||
std::string replacement;
|
||||
std::string where;
|
||||
};
|
||||
|
||||
void initDeprecation();
|
||||
void deinitDeprecation();
|
||||
|
||||
void setDeprecationOutputEnabled(bool enable);
|
||||
bool isDeprecationOutputEnabled();
|
||||
|
||||
std::string getDeprecationNotice(const DeprecationInfo &info, bool usewhere);
|
||||
|
||||
struct GetDeprecated
|
||||
{
|
||||
GetDeprecated();
|
||||
~GetDeprecated();
|
||||
|
||||
const std::vector<const DeprecationInfo *> &all;
|
||||
};
|
||||
|
||||
struct MarkDeprecated
|
||||
{
|
||||
MarkDeprecated(const char *name);
|
||||
MarkDeprecated(const char *name, DeprecationType type, const char *replacement);
|
||||
~MarkDeprecated();
|
||||
|
||||
DeprecationInfo *info;
|
||||
};
|
||||
|
||||
} // love
|
||||
@@ -786,6 +786,25 @@ lua_State *luax_getpinnedthread(lua_State *L)
|
||||
return thread;
|
||||
}
|
||||
|
||||
void luax_markdeprecated(lua_State *L, const char *name)
|
||||
{
|
||||
luax_markdeprecated(L, name, DEPRECATED_NO_REPLACEMENT, nullptr);
|
||||
}
|
||||
|
||||
void luax_markdeprecated(lua_State *L, const char *name, DeprecationType type, const char *replacement)
|
||||
{
|
||||
MarkDeprecated deprecated(name, type, replacement);
|
||||
|
||||
if (deprecated.info != nullptr && deprecated.info->uses == 1)
|
||||
{
|
||||
luaL_where(L, 1);
|
||||
const char *where = lua_tostring(L, -1);
|
||||
if (where != nullptr)
|
||||
deprecated.info->where = where;
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int luax_typerror(lua_State *L, int narg, const char *tname)
|
||||
{
|
||||
int argtype = lua_type(L, narg);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
// LOVE
|
||||
#include "types.h"
|
||||
#include "deprecation.h"
|
||||
|
||||
// Lua
|
||||
extern "C" {
|
||||
@@ -447,6 +448,13 @@ lua_State *luax_insistpinnedthread(lua_State *L);
|
||||
**/
|
||||
lua_State *luax_getpinnedthread(lua_State *L);
|
||||
|
||||
/**
|
||||
* Mark a function as deprecated. Should only be called inside wrapper function
|
||||
* code.
|
||||
**/
|
||||
void luax_markdeprecated(lua_State *L, const char *name);
|
||||
void luax_markdeprecated(lua_State *L, const char *name, DeprecationType type, const char *replacement);
|
||||
|
||||
extern "C" { // Also called from luasocket
|
||||
int luax_typerror(lua_State *L, int narg, const char *tname);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user