aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2022-12-20 08:44:19 +0100
committerGitHub <noreply@github.com>2022-12-20 07:44:19 +0000
commitd26553491b3efb3fce7cc626683342cd1fa4cbf3 (patch)
tree7edeafe8cb4454f83357d72c707556dedd026df4
parentfeat(functional): add trim_start and assoc (#779) (diff)
downloadmason-d26553491b3efb3fce7cc626683342cd1fa4cbf3.tar
mason-d26553491b3efb3fce7cc626683342cd1fa4cbf3.tar.gz
mason-d26553491b3efb3fce7cc626683342cd1fa4cbf3.tar.bz2
mason-d26553491b3efb3fce7cc626683342cd1fa4cbf3.tar.lz
mason-d26553491b3efb3fce7cc626683342cd1fa4cbf3.tar.xz
mason-d26553491b3efb3fce7cc626683342cd1fa4cbf3.tar.zst
mason-d26553491b3efb3fce7cc626683342cd1fa4cbf3.zip
feat(expr): use same context for value & filter evaluation (#778)
-rw-r--r--lua/mason-core/installer/registry/expr.lua38
-rw-r--r--tests/mason-core/installer/registry/expr_spec.lua34
2 files changed, 64 insertions, 8 deletions
diff --git a/lua/mason-core/installer/registry/expr.lua b/lua/mason-core/installer/registry/expr.lua
index be704156..2713fcc4 100644
--- a/lua/mason-core/installer/registry/expr.lua
+++ b/lua/mason-core/installer/registry/expr.lua
@@ -1,5 +1,4 @@
local _ = require "mason-core.functional"
-local string_funs = require "mason-core.functional.string"
local Result = require "mason-core.result"
local M = {}
@@ -14,14 +13,45 @@ local parse_expr = _.compose(
_.split "|"
)
+local FILTERS = {
+ format = _.format,
+ gsub = _.gsub,
+ to_lower = _.to_lower,
+ to_upper = _.to_upper,
+ trim = _.trim,
+ trim_start = _.trim_start,
+ tostring = tostring,
+}
+
+---@generic T : table
+---@param tbl T
+---@return T
+local function shallow_clone(tbl)
+ local res = {}
+ for k, v in pairs(tbl) do
+ res[k] = v
+ end
+ return res
+end
+
---@param str string
---@param ctx table<string, any>
function M.eval(str, ctx)
+ ctx = shallow_clone(ctx)
return Result.pcall(function()
+ setmetatable(ctx, { __index = FILTERS })
return _.gsub("{{([^}]+)}}", function(expr)
local components = parse_expr(expr)
- local value =
- assert(ctx[components.value_expr], ("Unable to interpolate value: %q."):format(components.value_expr))
+ local value = assert(
+ setfenv(
+ assert(
+ loadstring("return " .. components.value_expr),
+ ("Failed to parse value :%q."):format(components.value_expr)
+ ),
+ ctx
+ )(),
+ ("Value is nil: %q."):format(components.value_expr)
+ )
return _.reduce(
_.apply_to,
value,
@@ -31,7 +61,7 @@ function M.eval(str, ctx)
loadstring("return " .. filter_expr),
("Failed to parse filter: %q."):format(filter_expr)
),
- string_funs
+ ctx
)()
assert(type(filter) == "function", ("Invalid filter expression: %q."):format(filter_expr))
return filter
diff --git a/tests/mason-core/installer/registry/expr_spec.lua b/tests/mason-core/installer/registry/expr_spec.lua
index 7e662b79..ec92f7a7 100644
--- a/tests/mason-core/installer/registry/expr_spec.lua
+++ b/tests/mason-core/installer/registry/expr_spec.lua
@@ -4,7 +4,7 @@ local Result = require "mason-core.result"
describe("registry expressions", function()
it("should eval simple expressions", function()
- assert.same(Result.success "Hello, world!", expr.eval "Hello, world!")
+ assert.same(Result.success "Hello, world!", expr.eval("Hello, world!", {}))
assert.same(
Result.success "Hello, John Doe!",
@@ -15,6 +15,34 @@ describe("registry expressions", function()
)
end)
+ it("should eval nested access", function()
+ assert.same(
+ Result.success "Hello, world!",
+ expr.eval("Hello, {{greeting.name}}!", { greeting = { name = "world" } })
+ )
+ end)
+
+ it("should eval benign expressions", function()
+ assert.same(
+ Result.success "Hello, JOHNDOE JR.!",
+ expr.eval("Hello, {{greeting.firstname .. greeting.lastname .. tostring(tbl) | to_upper}}!", {
+ greeting = { firstname = "John", lastname = "Doe" },
+ tbl = setmetatable({}, {
+ __tostring = function()
+ return " Jr."
+ end,
+ }),
+ })
+ )
+
+ assert.same(
+ Result.success "Gloves",
+ expr.eval("G{{ 'Cloves' | trim_start(trim) }}", {
+ trim = "C",
+ })
+ )
+ end)
+
it("should eval expressions with filters", function()
assert.same(
Result.success "Hello, MR. John!",
@@ -35,9 +63,7 @@ describe("registry expressions", function()
it("should reject invalid values", function()
assert.is_true(
- match.matches [[^.*Unable to interpolate value: "non_existent"%.$]](
- expr.eval("Hello, {{non_existent}}", {}):err_or_nil()
- )
+ match.matches [[^.*Value is nil: "non_existent"%.$]](expr.eval("Hello, {{non_existent}}", {}):err_or_nil())
)
end)