Add ability to safely alias function names without breaking overrides

Introduces new calls premake.alias() and premake.resolveAlias()
This commit is contained in:
Jason Perkins 2015-07-28 16:50:42 -04:00
parent 2706449670
commit e84cc11412
3 changed files with 125 additions and 0 deletions

View File

@ -17,6 +17,9 @@
local _warnings = {} local _warnings = {}
-- Keep track of aliased functions, so I can resolve to canonical names
local _aliases = {}
-- --
-- Define some commonly used symbols, for future-proofing. -- Define some commonly used symbols, for future-proofing.
@ -51,6 +54,36 @@
---
-- Provide an alias for a function in a namespace. Calls to the alias will
-- invoke the canonical function, and attempts to override the alias will
-- instead override the canonical call.
--
-- @param scope
-- The table containing the function to be overridden. Use _G for
-- global functions.
-- @param canonical
-- The name of the function to be aliased (a string value)
-- @param alias
-- The new alias for the function (another string value).
---
function p.alias(scope, canonical, alias)
scope, canonical = p.resolveAlias(scope, canonical)
if not scope[canonical] then
error("unable to alias '" .. canonical .. "'; no such function", 2)
end
_aliases[scope] = _aliases[scope] or {}
_aliases[scope][alias] = canonical
scope[alias] = function(...)
return scope[canonical](...)
end
end
--- ---
-- Call a list of functions. -- Call a list of functions.
-- --
@ -230,10 +263,13 @@
--- ---
function premake.override(scope, name, repl) function premake.override(scope, name, repl)
scope, name = p.resolveAlias(scope, name)
local original = scope[name] local original = scope[name]
if not original then if not original then
error("unable to override '" .. name .. "'; no such function", 2) error("unable to override '" .. name .. "'; no such function", 2)
end end
scope[name] = function(...) scope[name] = function(...)
return repl(original, ...) return repl(original, ...)
end end
@ -253,6 +289,30 @@
---
-- Find the canonical name and scope of a function, resolving any aliases.
--
-- @param scope
-- The table containing the function to be overridden. Use _G for
-- global functions.
-- @param name
-- The name of the function to resolve.
-- @return
-- The canonical scope and function name (a string value).
---
function p.resolveAlias(scope, name)
local aliases = _aliases[scope]
if aliases then
while aliases[name] do
name = aliases[name]
end
end
return scope, name
end
-- --
-- Display a warning, with a formatted message built from the provided -- Display a warning, with a formatted message built from the provided
-- arguments. -- arguments.

View File

@ -1,6 +1,7 @@
return { return {
-- Base API tests -- Base API tests
"test_string.lua", "test_string.lua",
"base/test_aliasing.lua",
"base/test_configset.lua", "base/test_configset.lua",
"base/test_context.lua", "base/test_context.lua",
"base/test_criteria.lua", "base/test_criteria.lua",

View File

@ -0,0 +1,64 @@
--
-- tests/base/test_aliasing.lua
-- Verify handling of function aliases.
-- Copyright (c) 2015 Jason Perkins and the Premake project
--
local suite = test.declare("premake_alias")
local p = premake
function suite.setup()
suite.testfunc = function()
return 48
end
suite.aliased = nil
suite.aliased2 = nil
end
function suite.returnsOriginalFunction_onNoAlias()
local scope, f = p.resolveAlias(suite, "testfunc")
test.isequal("testfunc", f)
end
function suite.pointsAliasToOriginalFunction()
p.alias(suite, "testfunc", "aliased")
test.isequal(48, suite.aliased())
end
function suite.returnsOriginalFunction_onAlias()
p.alias(suite, "testfunc", "aliased")
local scope, f = p.resolveAlias(suite, "aliased")
test.isequal("testfunc", f)
end
function suite.returnsOriginalFunction_onChainedAliases()
p.alias(suite, "testfunc", "aliased")
p.alias(suite, "aliased", "aliased2")
local scope, f = p.resolveAlias(suite, "aliased2")
test.isequal("testfunc", f)
end
function suite.overrideResolvesAliases()
p.alias(suite, "testfunc", "aliased")
p.override(suite, "aliased", function(base)
return base() + 1
end)
test.isequal(49, suite.testfunc())
end
function suite.aliasTracksOverrides()
p.alias(suite, "testfunc", "aliased")
p.override(suite, "testfunc", function(base)
return base() + 1
end)
test.isequal(49, suite.aliased())
end