Skip to content

Commit 28c4dc2

Browse files
committed
Check that Lua functions on OSM object are called correctly
The code that deals with functions called on the Lua OSM object given as parameter to the process callbacks is somewhat strange. The result is that calling "object.as_point()" etc. will work, but the correct Lua way to do this is "object:as_point()". This adds a check to all the functions that detects this case and prints a warning. It will also check that those functions are not called with any additional arguments. Checking for this now, users will hopefully fix this. This gives us the opportunity later to change or code to be more in line with usual Lua syntax. This will only print a warning once per function.
1 parent 53fd9cc commit 28c4dc2

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

src/output-flex.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <limits>
4646
#include <memory>
4747
#include <mutex>
48+
#include <set>
4849
#include <stdexcept>
4950
#include <string>
5051
#include <string_view>
@@ -295,6 +296,40 @@ void create_expire_tables(std::vector<expire_output_t> const &expire_outputs,
295296
}
296297
}
297298

299+
void check_for_object(lua_State *lua_state, char const *const function_name)
300+
{
301+
// This is used to make sure we are printing warnings only once per
302+
// function name.
303+
static std::set<std::string> message_shown;
304+
if (message_shown.count(function_name)) {
305+
return;
306+
}
307+
308+
int const num_params = lua_gettop(lua_state);
309+
if (num_params == 0) {
310+
log_warn("You should use the syntax 'object:{}()' (with the colon, not "
311+
"a point) to call functions on the OSM object.",
312+
function_name);
313+
314+
message_shown.emplace(function_name);
315+
return;
316+
}
317+
318+
if (lua_getmetatable(lua_state, 1)) {
319+
luaL_getmetatable(lua_state, osm2pgsql_object_metatable.data());
320+
if (lua_rawequal(lua_state, -1, -2)) {
321+
lua_pop(lua_state, 2); // remove the two metatables
322+
return;
323+
}
324+
lua_pop(lua_state, 2); // remove the two metatables
325+
}
326+
327+
message_shown.emplace(function_name);
328+
log_warn("First and only parameter for {0}() must be the OSM object. Call "
329+
"it like this: 'object:{0}()'.",
330+
function_name);
331+
}
332+
298333
} // anonymous namespace
299334

300335
/**
@@ -304,6 +339,8 @@ void create_expire_tables(std::vector<expire_output_t> const &expire_outputs,
304339
void output_flex_t::check_context_and_state(char const *name,
305340
char const *context, bool condition)
306341
{
342+
check_for_object(lua_state(), name);
343+
307344
if (condition) {
308345
throw fmt_error(
309346
"The function {}() can only be called (directly or indirectly) "

0 commit comments

Comments
 (0)