diff options
| author | William Boman <william@redwill.se> | 2022-12-20 08:44:19 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-20 07:44:19 +0000 |
| commit | d26553491b3efb3fce7cc626683342cd1fa4cbf3 (patch) | |
| tree | 7edeafe8cb4454f83357d72c707556dedd026df4 | |
| parent | feat(functional): add trim_start and assoc (#779) (diff) | |
| download | mason-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.lua | 38 | ||||
| -rw-r--r-- | tests/mason-core/installer/registry/expr_spec.lua | 34 |
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) |
