Skip to content

Commit 49509d2

Browse files
authoredJul 1, 2018
Log deprecated Lua function calls (#7491)
1 parent 6f22d14 commit 49509d2

File tree

6 files changed

+96
-7
lines changed

6 files changed

+96
-7
lines changed
 

Diff for: ‎src/script/lua_api/l_base.cpp

+79
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2121
#include "lua_api/l_internal.h"
2222
#include "cpp_api/s_base.h"
2323
#include "content/mods.h"
24+
#include "profiler.h"
2425
#include "server.h"
26+
#include <algorithm>
2527
#include <cmath>
2628

2729
ScriptApiBase *ModApiBase::getScriptApiBase(lua_State *L)
@@ -85,3 +87,80 @@ bool ModApiBase::registerFunction(lua_State *L, const char *name,
8587

8688
return true;
8789
}
90+
91+
std::unordered_map<std::string, luaL_Reg> ModApiBase::m_deprecated_wrappers;
92+
bool ModApiBase::m_error_deprecated_calls = false;
93+
94+
int ModApiBase::l_deprecated_function(lua_State *L)
95+
{
96+
thread_local std::vector<u64> deprecated_logged;
97+
98+
u64 start_time = porting::getTimeUs();
99+
lua_Debug ar;
100+
101+
// Get function name for lookup
102+
FATAL_ERROR_IF(!lua_getstack(L, 0, &ar), "lua_getstack() failed");
103+
FATAL_ERROR_IF(!lua_getinfo(L, "n", &ar), "lua_getinfo() failed");
104+
105+
// Combine name with line and script backtrace
106+
FATAL_ERROR_IF(!lua_getstack(L, 1, &ar), "lua_getstack() failed");
107+
FATAL_ERROR_IF(!lua_getinfo(L, "Sl", &ar), "lua_getinfo() failed");
108+
109+
// Get parent class to get the wrappers map
110+
luaL_checktype(L, 1, LUA_TUSERDATA);
111+
void *ud = lua_touserdata(L, 1);
112+
ModApiBase *o = *(ModApiBase**)ud;
113+
114+
// New function and new function name
115+
auto it = o->m_deprecated_wrappers.find(ar.name);
116+
117+
// Get backtrace and hash it to reduce the warning flood
118+
std::string backtrace = ar.short_src;
119+
backtrace.append(":").append(std::to_string(ar.currentline));
120+
u64 hash = murmur_hash_64_ua(backtrace.data(), backtrace.length(), 0xBADBABE);
121+
122+
if (std::find(deprecated_logged.begin(), deprecated_logged.end(), hash)
123+
== deprecated_logged.end()) {
124+
125+
deprecated_logged.emplace_back(hash);
126+
warningstream << "Call to deprecated function '" << ar.name << "', please use '"
127+
<< it->second.name << "' at " << backtrace << std::endl;
128+
129+
if (m_error_deprecated_calls)
130+
script_error(L, LUA_ERRRUN, NULL, NULL);
131+
}
132+
133+
u64 end_time = porting::getTimeUs();
134+
g_profiler->avg("l_deprecated_function", end_time - start_time);
135+
136+
return it->second.func(L);
137+
}
138+
139+
void ModApiBase::markAliasDeprecated(luaL_Reg *reg)
140+
{
141+
std::string value = g_settings->get("deprecated_lua_api_handling");
142+
m_error_deprecated_calls = value == "error";
143+
144+
if (!m_error_deprecated_calls && value != "log")
145+
return;
146+
147+
const char *last_name = nullptr;
148+
lua_CFunction last_func = nullptr;
149+
150+
// ! Null termination !
151+
while (reg->func) {
152+
if (last_func == reg->func) {
153+
// Duplicate found
154+
std::pair<std::string, luaL_Reg> entry(
155+
reg->name,
156+
{ .name = last_name, .func = reg->func }
157+
);
158+
m_deprecated_wrappers.emplace(entry);
159+
reg->func = l_deprecated_function;
160+
}
161+
162+
last_func = reg->func;
163+
last_name = reg->name;
164+
++reg;
165+
}
166+
}

Diff for: ‎src/script/lua_api/l_base.h

+8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2323
#include "common/c_internal.h"
2424
#include "common/helper.h"
2525
#include "gamedef.h"
26+
#include <unordered_map>
2627

2728
extern "C" {
2829
#include <lua.h>
@@ -70,4 +71,11 @@ class ModApiBase : protected LuaHelper {
7071
const char* name,
7172
lua_CFunction func,
7273
int top);
74+
75+
static int l_deprecated_function(lua_State *L);
76+
static void markAliasDeprecated(luaL_Reg *reg);
77+
private:
78+
// <old_name> = { <new_name>, <new_function> }
79+
static std::unordered_map<std::string, luaL_Reg> m_deprecated_wrappers;
80+
static bool m_error_deprecated_calls;
7381
};

Diff for: ‎src/script/lua_api/l_noise.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ void LuaPerlinNoise::Register(lua_State *L)
122122

123123
lua_pop(L, 1);
124124

125+
markAliasDeprecated(methods);
125126
luaL_openlib(L, 0, methods, 0);
126127
lua_pop(L, 1);
127128

@@ -130,7 +131,7 @@ void LuaPerlinNoise::Register(lua_State *L)
130131

131132

132133
const char LuaPerlinNoise::className[] = "PerlinNoise";
133-
const luaL_Reg LuaPerlinNoise::methods[] = {
134+
luaL_Reg LuaPerlinNoise::methods[] = {
134135
luamethod_aliased(LuaPerlinNoise, get_2d, get2d),
135136
luamethod_aliased(LuaPerlinNoise, get_3d, get3d),
136137
{0,0}
@@ -380,6 +381,7 @@ void LuaPerlinNoiseMap::Register(lua_State *L)
380381

381382
lua_pop(L, 1);
382383

384+
markAliasDeprecated(methods);
383385
luaL_openlib(L, 0, methods, 0);
384386
lua_pop(L, 1);
385387

@@ -388,7 +390,7 @@ void LuaPerlinNoiseMap::Register(lua_State *L)
388390

389391

390392
const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
391-
const luaL_Reg LuaPerlinNoiseMap::methods[] = {
393+
luaL_Reg LuaPerlinNoiseMap::methods[] = {
392394
luamethod_aliased(LuaPerlinNoiseMap, get_2d_map, get2dMap),
393395
luamethod_aliased(LuaPerlinNoiseMap, get_2d_map_flat, get2dMap_flat),
394396
luamethod_aliased(LuaPerlinNoiseMap, calc_2d_map, calc2dMap),

Diff for: ‎src/script/lua_api/l_noise.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class LuaPerlinNoise : public ModApiBase
3131
private:
3232
NoiseParams np;
3333
static const char className[];
34-
static const luaL_Reg methods[];
34+
static luaL_Reg methods[];
3535

3636
// Exported functions
3737

@@ -63,7 +63,7 @@ class LuaPerlinNoiseMap : public ModApiBase
6363
Noise *noise;
6464
bool m_is3d;
6565
static const char className[];
66-
static const luaL_Reg methods[];
66+
static luaL_Reg methods[];
6767

6868
// Exported functions
6969

Diff for: ‎src/script/lua_api/l_object.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1815,6 +1815,7 @@ void ObjectRef::Register(lua_State *L)
18151815

18161816
lua_pop(L, 1); // drop metatable
18171817

1818+
markAliasDeprecated(methods);
18181819
luaL_openlib(L, 0, methods, 0); // fill methodtable
18191820
lua_pop(L, 1); // drop methodtable
18201821

@@ -1823,7 +1824,7 @@ void ObjectRef::Register(lua_State *L)
18231824
}
18241825

18251826
const char ObjectRef::className[] = "ObjectRef";
1826-
const luaL_Reg ObjectRef::methods[] = {
1827+
luaL_Reg ObjectRef::methods[] = {
18271828
// ServerActiveObject
18281829
luamethod(ObjectRef, remove),
18291830
luamethod_aliased(ObjectRef, get_pos, getpos),

Diff for: ‎src/script/lua_api/l_object.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,8 @@ class ObjectRef : public ModApiBase {
5050
static ServerActiveObject* getobject(ObjectRef *ref);
5151
private:
5252
ServerActiveObject *m_object = nullptr;
53-
5453
static const char className[];
55-
static const luaL_Reg methods[];
54+
static luaL_Reg methods[];
5655

5756

5857
static LuaEntitySAO* getluaobject(ObjectRef *ref);

0 commit comments

Comments
 (0)
Please sign in to comment.