From e84cc11412847d011c29a2ff9c508d04d6d41787 Mon Sep 17 00:00:00 2001 From: Jason Perkins Date: Tue, 28 Jul 2015 16:50:42 -0400 Subject: [PATCH] Add ability to safely alias function names without breaking overrides Introduces new calls premake.alias() and premake.resolveAlias() --- src/base/_foundation.lua | 60 +++++++++++++++++++++++++++++++++ tests/_tests.lua | 1 + tests/base/test_aliasing.lua | 64 ++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 tests/base/test_aliasing.lua diff --git a/src/base/_foundation.lua b/src/base/_foundation.lua index 8cf1bfda..2d23d9bf 100644 --- a/src/base/_foundation.lua +++ b/src/base/_foundation.lua @@ -17,6 +17,9 @@ local _warnings = {} +-- Keep track of aliased functions, so I can resolve to canonical names + + local _aliases = {} -- -- 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. -- @@ -230,10 +263,13 @@ --- function premake.override(scope, name, repl) + scope, name = p.resolveAlias(scope, name) + local original = scope[name] if not original then error("unable to override '" .. name .. "'; no such function", 2) end + scope[name] = function(...) return repl(original, ...) 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 -- arguments. diff --git a/tests/_tests.lua b/tests/_tests.lua index 451224f2..6cf9d1cc 100644 --- a/tests/_tests.lua +++ b/tests/_tests.lua @@ -1,6 +1,7 @@ return { -- Base API tests "test_string.lua", + "base/test_aliasing.lua", "base/test_configset.lua", "base/test_context.lua", "base/test_criteria.lua", diff --git a/tests/base/test_aliasing.lua b/tests/base/test_aliasing.lua new file mode 100644 index 00000000..27e9e43f --- /dev/null +++ b/tests/base/test_aliasing.lua @@ -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 +