Move config set value fetches to new field framework
This commit is contained in:
parent
974b622b82
commit
9378d31295
@ -306,7 +306,7 @@
|
||||
local target = api.gettarget(field.scope)
|
||||
|
||||
if not value then
|
||||
return configset.fetchvalue(target.configset, field.name)
|
||||
return configset.fetch(target.configset, field)
|
||||
end
|
||||
|
||||
local status, result = pcall(function ()
|
||||
@ -367,7 +367,7 @@
|
||||
end
|
||||
|
||||
if value:contains("*") then
|
||||
local current = configset.fetchvalue(target.configset, field.name)
|
||||
local current = configset.fetch(target.configset, field)
|
||||
local mask = path.wildcards(value)
|
||||
for _, item in ipairs(current) do
|
||||
if item:match(mask) == item then
|
||||
@ -775,6 +775,99 @@
|
||||
end
|
||||
|
||||
|
||||
|
||||
premake.field.kind("boolean", {
|
||||
|
||||
})
|
||||
|
||||
premake.field.kind("directory", {
|
||||
|
||||
})
|
||||
|
||||
premake.field.kind("file", {
|
||||
|
||||
})
|
||||
|
||||
premake.field.kind("integer", {
|
||||
|
||||
})
|
||||
|
||||
--
|
||||
-- Key-value data kind definition. Merges key domains; values may be any kind.
|
||||
--
|
||||
|
||||
local function setKeyed(field, current, value, processor)
|
||||
current = current or {}
|
||||
|
||||
for k, v in pairs(value) do
|
||||
if type(k) == "number" then
|
||||
current = setKeyed(field, current, v, processor)
|
||||
else
|
||||
if processor then
|
||||
v = processor(field, current[k], v)
|
||||
end
|
||||
current[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
return current
|
||||
end
|
||||
|
||||
premake.field.kind("keyed", {
|
||||
merge = setKeyed
|
||||
})
|
||||
|
||||
|
||||
--
|
||||
-- List data kind definition. Actually a misnomer, lists are more like sets in
|
||||
-- that duplicate values are weeded out; each will only appear once. Can
|
||||
-- contain any other kind of data.
|
||||
--
|
||||
|
||||
local function setList(field, current, value, processor)
|
||||
if type(value) == "table" then
|
||||
for _, item in ipairs(value) do
|
||||
current = setList(field, current, item, processor)
|
||||
end
|
||||
return current
|
||||
end
|
||||
|
||||
current = current or {}
|
||||
|
||||
if current[value] then
|
||||
table.remove(current, table.indexof(current, value))
|
||||
end
|
||||
|
||||
table.insert(current, value)
|
||||
current[value] = value
|
||||
return current
|
||||
end
|
||||
|
||||
premake.field.kind("list", {
|
||||
merge = setList,
|
||||
})
|
||||
|
||||
premake.field.kind("mixed", {
|
||||
|
||||
})
|
||||
|
||||
premake.field.kind("number", {
|
||||
|
||||
})
|
||||
|
||||
premake.field.kind("path", {
|
||||
|
||||
})
|
||||
|
||||
premake.field.kind("string", {
|
||||
|
||||
})
|
||||
|
||||
premake.field.kind("table", {
|
||||
|
||||
})
|
||||
|
||||
|
||||
--
|
||||
-- Start a new block of configuration settings.
|
||||
--
|
||||
|
@ -1,19 +1,16 @@
|
||||
--
|
||||
-- configset.lua
|
||||
--
|
||||
-- DO NOT USE THIS YET! I am just getting started here; please wait until
|
||||
-- I've had a chance to build it out more before using.
|
||||
-- A configuration set manages a collection of fields, which are organized
|
||||
-- into "blocks". Each block stores a set of field-value pairs, along with
|
||||
-- a list of terms which indicate the context in which those field values
|
||||
-- should be applied.
|
||||
--
|
||||
-- A configuration set manages a collection of configuration values, which
|
||||
-- are organized into "blocks". Each block stores a set of field-value pairs,
|
||||
-- along with a list of terms which indicate the context in which those
|
||||
-- values should be applied.
|
||||
--
|
||||
-- Configurations use the API definition to know what fields are available,
|
||||
-- Configurations use the field definitions to know what fields are available,
|
||||
-- and the corresponding value types for those fields. Only fields that have
|
||||
-- been registered via api.register() can be stored.
|
||||
-- been registered via field.new() can be stored.
|
||||
--
|
||||
-- Copyright (c) 2012 Jason Perkins and the Premake project
|
||||
-- Copyright (c) 2012-2014 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
premake.configset = {}
|
||||
@ -43,6 +40,103 @@
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- Retrieve a value from the configuration set.
|
||||
--
|
||||
-- @param cset
|
||||
-- The configuration set to query.
|
||||
-- @param field
|
||||
-- The definition of field to be queried.
|
||||
-- @param context
|
||||
-- A list of lowercase context terms to use during the fetch. Only those
|
||||
-- blocks with terms fully contained by this list will be considered in
|
||||
-- determining the returned value. Terms should be lower case to make
|
||||
-- the context filtering case-insensitive.
|
||||
-- @param filename
|
||||
-- An optional filename; if provided, only blocks with pattern that
|
||||
-- matches the name will be considered.
|
||||
-- @return
|
||||
-- The requested value.
|
||||
---
|
||||
|
||||
function configset.fetch(cset, field, context, filename)
|
||||
if not context then
|
||||
context = cset._current._criteria.terms
|
||||
end
|
||||
|
||||
if premake.field.merges(field) then
|
||||
return configset._fetchMerged(cset, field, context, filename)
|
||||
else
|
||||
return configset._fetchDirect(cset, field, context, filename)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function configset._fetchDirect(cset, field, filter, filename)
|
||||
local key = field.name
|
||||
|
||||
local n = #cset._blocks
|
||||
for i = n, 1, -1 do
|
||||
local block = cset._blocks[i]
|
||||
local value = block[key]
|
||||
if value and (cset.compiled or configset.testblock(block, filter, filename)) then
|
||||
-- If value is an object, return a copy of it so that any
|
||||
-- changes later made to it by the caller won't alter the
|
||||
-- original value (that was a tough bug to find)
|
||||
if type(value) == "table" then
|
||||
value = table.deepcopy(value)
|
||||
end
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
||||
if cset._parent then
|
||||
return configset._fetchDirect(cset._parent, field, filter, filename)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function configset._fetchMerged(cset, field, filter, filename)
|
||||
local result = {}
|
||||
|
||||
local function remove(patterns)
|
||||
for _, pattern in ipairs(patterns) do
|
||||
local i = 1
|
||||
while i <= #result do
|
||||
local value = result[i]:lower()
|
||||
if value:match(pattern) == value then
|
||||
result[result[i]] = nil
|
||||
table.remove(result, i)
|
||||
else
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if cset._parent then
|
||||
result = configset._fetchMerged(cset._parent, field, filter, filename)
|
||||
end
|
||||
|
||||
local key = field.name
|
||||
for _, block in ipairs(cset._blocks) do
|
||||
if cset.compiled or configset.testblock(block, filter, filename) then
|
||||
if block._removes and block._removes[key] then
|
||||
remove(block._removes[key])
|
||||
end
|
||||
|
||||
local value = block[key]
|
||||
if value then
|
||||
result = premake.field.merge(field, result, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Create and return a metatable which allows a configuration set to act as a
|
||||
-- "backing store" for a regular Lua table. Table operations that access a
|
||||
@ -64,7 +158,7 @@
|
||||
__index = function(tbl, key)
|
||||
local f = premake.field.get(key)
|
||||
if f then
|
||||
return configset.fetchvalue(cset, f.name, cset._current._criteria.terms)
|
||||
return configset.fetch(cset, f, cset._current._criteria.terms)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
@ -74,7 +168,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Register a field that requires special handling.
|
||||
--
|
||||
@ -94,6 +187,7 @@
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Create a new block of configuration field-value pairs, with the provided
|
||||
-- set of context terms to control their application.
|
||||
@ -123,6 +217,7 @@
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Add a new field-value pair to the current configuration data block. The
|
||||
-- data type of the field is taken into account when adding the values:
|
||||
@ -154,6 +249,7 @@
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Remove values from a configuration set.
|
||||
--
|
||||
@ -183,6 +279,7 @@
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Check to see if a configuration set is empty; that is, it does
|
||||
-- not contain any configuration blocks.
|
||||
@ -198,12 +295,13 @@
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Check to see if an individual configuration block applies to the
|
||||
-- given context and filename.
|
||||
--
|
||||
|
||||
local function testblock(block, context, filename)
|
||||
function configset.testblock(block, context, filename)
|
||||
-- Make file tests relative to the blocks base directory,
|
||||
-- so path relative pattern matches will work.
|
||||
if block._basedir and filename then
|
||||
@ -213,6 +311,7 @@
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Compiles a new configuration set containing only the blocks which match
|
||||
-- the specified criteria. Fetches against this compiled configuration set
|
||||
@ -245,7 +344,7 @@
|
||||
|
||||
-- add in my own blocks
|
||||
for _, block in ipairs(cset._blocks) do
|
||||
if testblock(block, context, filename) then
|
||||
if configset.testblock(block, context, filename) then
|
||||
table.insert(result._blocks, block)
|
||||
end
|
||||
end
|
||||
@ -255,181 +354,4 @@
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Merges two lists of values together. The merged list is both indexed
|
||||
-- and keyed for faster lookups. If duplicate values are encountered,
|
||||
-- the earlier value is removed.
|
||||
--
|
||||
|
||||
local function merge(a, b)
|
||||
-- if b is itself a list, flatten it out
|
||||
if type(b) == "table" then
|
||||
for _, v in ipairs(b) do
|
||||
merge(a, v)
|
||||
end
|
||||
|
||||
-- if b is a simple value, insert it
|
||||
else
|
||||
-- find and remove earlier values
|
||||
if a[b] then
|
||||
table.remove(a, table.indexof(a, b))
|
||||
end
|
||||
|
||||
table.insert(a, b)
|
||||
a[b] = b
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve a directly assigned value from the configuration set. No merging
|
||||
-- takes place; the last value set is the one returned.
|
||||
--
|
||||
|
||||
local function fetchassign(cset, fieldname, context, filename)
|
||||
-- walk the loop backwards and return on first value encountered
|
||||
local n = #cset._blocks
|
||||
for i = n, 1, -1 do
|
||||
local block = cset._blocks[i]
|
||||
if block[fieldname] and (cset.compiled or testblock(block, context, filename)) then
|
||||
return block[fieldname]
|
||||
end
|
||||
end
|
||||
|
||||
if cset._parent then
|
||||
return fetchassign(cset._parent, fieldname, context, filename)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve a keyed from the configuration set; keys are assembled into
|
||||
-- a single result; values may optionally be merged too.
|
||||
--
|
||||
|
||||
local function fetchkeyed(cset, fieldname, context, filename, mergevalues)
|
||||
local result = {}
|
||||
|
||||
-- grab values from the parent set first
|
||||
if cset._parent then
|
||||
result = fetchkeyed(cset._parent, fieldname, context, filename, merge)
|
||||
end
|
||||
|
||||
function process(values)
|
||||
for k, v in pairs(values) do
|
||||
if type(k) == "number" then
|
||||
process(v)
|
||||
elseif mergevalues then
|
||||
result[k] = result[k] or {}
|
||||
merge(result[k], v)
|
||||
else
|
||||
result[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, block in ipairs(cset._blocks) do
|
||||
if cset.compiled or testblock(block, context, filename) then
|
||||
local value = block[fieldname]
|
||||
if value then
|
||||
process(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve a merged value from the configuration set; all values are
|
||||
-- assembled together into a single result.
|
||||
--
|
||||
|
||||
local function fetchmerge(cset, fieldname, context, filename)
|
||||
local result = {}
|
||||
|
||||
-- grab values from the parent set first
|
||||
if cset._parent then
|
||||
result = fetchmerge(cset._parent, fieldname, context, filename)
|
||||
end
|
||||
|
||||
function remove(patterns)
|
||||
for _, pattern in ipairs(patterns) do
|
||||
local i = 1
|
||||
while i <= #result do
|
||||
local value = result[i]:lower()
|
||||
if value:match(pattern) == value then
|
||||
result[result[i]] = nil
|
||||
table.remove(result, i)
|
||||
else
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, block in ipairs(cset._blocks) do
|
||||
if cset.compiled or testblock(block, context, filename) then
|
||||
if block._removes and block._removes[fieldname] then
|
||||
remove(block._removes[fieldname])
|
||||
end
|
||||
|
||||
local value = block[fieldname]
|
||||
if value then
|
||||
merge(result, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve a value from the configuration set.
|
||||
--
|
||||
-- @param cset
|
||||
-- The configuration set to query.
|
||||
-- @param fieldname
|
||||
-- The name of the field to query. The field should have already been
|
||||
-- defined using the api.register() function.
|
||||
-- @param context
|
||||
-- A list of lowercase context terms to use during the fetch. Only those
|
||||
-- blocks with terms fully contained by this list will be considered in
|
||||
-- determining the returned value. Terms should be lower case to make
|
||||
-- the context filtering case-insensitive.
|
||||
-- @param filename
|
||||
-- An optional filename; if provided, only blocks with pattern that
|
||||
-- matches the name will be considered.
|
||||
-- @return
|
||||
-- The requested value.
|
||||
--
|
||||
|
||||
function configset.fetchvalue(cset, fieldname, context, filename)
|
||||
local value
|
||||
|
||||
if not context then
|
||||
context = cset._current._criteria.terms
|
||||
end
|
||||
|
||||
-- should this field be merged or assigned?
|
||||
local field = configset._fields[fieldname]
|
||||
local keyed = field and field.keyed
|
||||
local merge = field and field.merge
|
||||
|
||||
if keyed then
|
||||
value = fetchkeyed(cset, fieldname, context, filename, merge)
|
||||
elseif merge then
|
||||
value = fetchmerge(cset, fieldname, context, filename)
|
||||
else
|
||||
value = fetchassign(cset, fieldname, context, filename)
|
||||
-- if value is an object, return a copy of it, so that they can
|
||||
-- modified by the caller without altering the source data
|
||||
if type(value) == "table" then
|
||||
value = table.deepcopy(value)
|
||||
end
|
||||
end
|
||||
|
||||
return value
|
||||
end
|
||||
|
@ -164,9 +164,9 @@
|
||||
-- If there is a matching field, then go fetch the aggregated value
|
||||
-- from my configuration set, and then cache it future lookups.
|
||||
|
||||
local value = configset.fetchvalue(ctx._cfgset, key, ctx.terms, ctx._filename[1])
|
||||
local value = configset.fetch(ctx._cfgset, field, ctx.terms, ctx._filename[1])
|
||||
if value then
|
||||
-- do I need to expand tokens? -- local field = premake.fields[key]
|
||||
-- do I need to expand tokens?
|
||||
if field and field.tokens then
|
||||
local kind = field.kind
|
||||
local ispath = kind:startswith("path") or kind:startswith("file") or kind:startswith("mixed")
|
||||
|
@ -24,6 +24,9 @@
|
||||
-- For historical reasons
|
||||
premake.fields = field._list
|
||||
|
||||
-- A cache for data kind accessor functions
|
||||
|
||||
field._accessors = {}
|
||||
|
||||
|
||||
---
|
||||
@ -46,12 +49,133 @@
|
||||
---
|
||||
|
||||
function field.new(f)
|
||||
-- Translate the old approaches to data kind definitions to the new
|
||||
-- one used here. These should probably be deprecated eventually.
|
||||
|
||||
local kind = f.kind
|
||||
|
||||
if f.list then
|
||||
kind = "list:" .. kind
|
||||
end
|
||||
|
||||
if f.keyed then
|
||||
kind = "keyed:" .. kind
|
||||
end
|
||||
|
||||
f._kind = kind
|
||||
|
||||
field._list[f.name] = f
|
||||
return f
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Register a new kind of data for field storage.
|
||||
--
|
||||
-- @param tag
|
||||
-- A unique name of the kind; used in the kind string in new field
|
||||
-- definitions (see new(), above).
|
||||
-- @param functions
|
||||
-- A table of processor functions for the new kind.
|
||||
---
|
||||
|
||||
function field.kind(tag, functions)
|
||||
field._kinds[tag] = functions
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Build an "accessor" function to process incoming values for a field. This
|
||||
-- function should be an interview question.
|
||||
--
|
||||
-- An accessor function takes the form of:
|
||||
--
|
||||
-- function (field, current, value, nextAccessor)
|
||||
--
|
||||
-- It receives the target field, the current value of that field, and the new
|
||||
-- value that has been provided by the project script. It then returns the
|
||||
-- new value for the target field.
|
||||
--
|
||||
-- @param f
|
||||
-- The field for which an accessor should be returned.
|
||||
-- @param method
|
||||
-- The type of accessor function required; currently this should be one of
|
||||
-- "set", "remove", or "merge" though it is possible for add-on modules to
|
||||
-- extend the available methods by implementing appropriate processing
|
||||
-- functions.
|
||||
-- @return
|
||||
-- An accessor function for the field's kind and method. May return nil
|
||||
-- if no processing functions are available for the given method.
|
||||
---
|
||||
|
||||
|
||||
function field.accessor(f, method)
|
||||
-- Prepare a cache for accessors using this method; each encountered
|
||||
-- kind only needs to be fully processed once.
|
||||
|
||||
field._accessors[method] = field._accessors[method] or {}
|
||||
local cache = field._accessors[method]
|
||||
|
||||
-- Helper function recurses over each piece of the field's data kind,
|
||||
-- building an accessor function for each sequence encountered. Results
|
||||
-- cached from earlier calls are reused again.
|
||||
|
||||
local function accessorForKind(kind)
|
||||
-- Have I already cached a result from an earlier call?
|
||||
if cache[kind] then
|
||||
return cache[kind]
|
||||
end
|
||||
|
||||
-- Split off the first piece from the rest of the kind. If the
|
||||
-- incoming kind is "list:key:string", thisKind will "list" and
|
||||
-- nextKind will be "key:string".
|
||||
|
||||
local thisKind = kind:match('(.-):') or kind
|
||||
local nextKind = kind:sub(#thisKind + 2)
|
||||
|
||||
-- Get the processor function for this kind. Processors perform
|
||||
-- data validation and storage appropriate for the data structure.
|
||||
|
||||
local functions = field._kinds[thisKind]
|
||||
if not functions then
|
||||
error("Invalid field kind '" .. thisKind .. "'")
|
||||
end
|
||||
|
||||
local processor = functions[method]
|
||||
if not processor then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Now recurse to get the accessor function for the remaining parts
|
||||
-- of the field's data kind. If the kind was "list:key:string", then
|
||||
-- the processor function handles the "list" part, and this function
|
||||
-- takes care of the "key:string" part.
|
||||
|
||||
local nextAccessor = accessorForKind(nextKind)
|
||||
|
||||
-- Now here's the magic: wrap the processor and the next accessor
|
||||
-- up together into a Matryoshka doll of function calls, each call
|
||||
-- handling just it's level of the kind.
|
||||
|
||||
accessor = function(f, current, value)
|
||||
return processor(f, current, value, nextAccessor)
|
||||
end
|
||||
|
||||
-- And cache the result so I don't have to go through that again
|
||||
cache[kind] = accessor
|
||||
return accessor
|
||||
end
|
||||
|
||||
-- The _kind is temporary; I'm using it while I transition off the old
|
||||
-- codebase. Once everything is migrated it can go away.
|
||||
|
||||
return accessorForKind(f._kind or f.kind)
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Fetch a field description by name.
|
||||
---
|
||||
@ -59,3 +183,25 @@
|
||||
function field.get(name)
|
||||
return field._list[name]
|
||||
end
|
||||
|
||||
|
||||
|
||||
function field.merge(f, current, value)
|
||||
local processor = field.accessor(f, "merge")
|
||||
if processor then
|
||||
return processor(f, current, value)
|
||||
else
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- Is this a field that supports merging values together? Non-merging fields
|
||||
-- can simply overwrite their values, merging fields can call merge() to
|
||||
-- combine two values together.
|
||||
---
|
||||
|
||||
function field.merges(f)
|
||||
return (field.accessor(f, "merge") ~= nil)
|
||||
end
|
||||
|
@ -362,7 +362,7 @@
|
||||
-- assemble all matching configmaps, and then merge their keys
|
||||
-- into the project's configmap
|
||||
|
||||
local map = configset.fetchvalue(cset, "configmap", terms)
|
||||
local map = configset.fetch(cset, premake.field.get("configmap"), terms)
|
||||
if map then
|
||||
for key, value in pairs(map) do
|
||||
ctx.configmap[key] = value
|
||||
|
@ -1,151 +0,0 @@
|
||||
--
|
||||
-- tests/api/test_callback.lua
|
||||
-- Tests the main API value-setting callback.
|
||||
-- Copyright (c) 2012 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
T.api_callback = {}
|
||||
local suite = T.api_callback
|
||||
local api = premake.api
|
||||
|
||||
|
||||
--
|
||||
-- Setup and teardown
|
||||
--
|
||||
|
||||
function suite.setup()
|
||||
api.settest = function(target, name, field, value)
|
||||
test_args = {
|
||||
["target"] = target,
|
||||
["name"] = name,
|
||||
["field"] = field,
|
||||
["value"] = value
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function suite.teardown()
|
||||
testapi = nil
|
||||
test_args = nil
|
||||
api.settest = nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Verify that the callback hands off control to setter for
|
||||
-- the field's value kind.
|
||||
--
|
||||
|
||||
function suite.callsSetter_onFieldKind()
|
||||
api.register { name = "testapi", kind = "test", scope = "project" }
|
||||
solution "MySolution"
|
||||
testapi "test"
|
||||
test.isnotnil(test_args)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Verify that the target field name is getting passed to the setter.
|
||||
--
|
||||
|
||||
function suite.setterGetsFieldName()
|
||||
api.register { name = "testapi", kind = "test", scope = "project" }
|
||||
solution "MySolution"
|
||||
testapi "test"
|
||||
test.isequal("testapi", test_args.name)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Verify that the field description is passed along to the setter.
|
||||
--
|
||||
|
||||
function suite.setterGetsFieldDescription()
|
||||
api.register { name = "testapi", kind = "test", scope = "project" }
|
||||
solution "MySolution"
|
||||
testapi "test"
|
||||
test.isequal("testapi", test_args.field.name)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Verify that the value is passed along to the setter.
|
||||
--
|
||||
|
||||
function suite.setterGetsFieldDescription()
|
||||
api.register { name = "testapi", kind = "test", scope = "project" }
|
||||
solution "MySolution"
|
||||
testapi "test"
|
||||
test.isequal("test", test_args.value)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If the field scope is "project" and there is an active solution, but not an
|
||||
-- active project, the solution should be the target.
|
||||
--
|
||||
|
||||
function suite.solutionTarget_onProjectScopeWithActiveSolution()
|
||||
api.register { name = "testapi", kind = "test", scope = "project" }
|
||||
local sln = solution "MySolution"
|
||||
testapi "test"
|
||||
test.istrue(sln == test_args.target)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If the field scope is "project" and there is an active project, it should
|
||||
-- be the target.
|
||||
--
|
||||
|
||||
function suite.projectTarget_onProjectScopeWithActiveProject()
|
||||
api.register { name = "testapi", kind = "test", scope = "project" }
|
||||
local sln = solution "MySolution"
|
||||
local prj = project "MyProject"
|
||||
testapi "test"
|
||||
test.istrue(prj == test_args.target)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If the field scope is "configuration" and there is an active configuration,
|
||||
-- it should be the target.
|
||||
--
|
||||
|
||||
function suite.configTarget_onConfigScopeWithActiveConfig()
|
||||
api.register { name = "testapi", kind = "test", scope = "configuration" }
|
||||
local sln = solution "MySolution"
|
||||
local cfg = configuration {}
|
||||
testapi "test"
|
||||
test.istrue(cfg == test_args.target)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- On key-value APIs, the field name should be the key value from the supplied table.
|
||||
--
|
||||
|
||||
function suite.keyObjectName_onKeyValue()
|
||||
api.register { name = "testapi", kind = "test", keyed = true, scope = "project" }
|
||||
local sln = solution "MySolution"
|
||||
testapi { key = "test" }
|
||||
test.isequal("key", test_args.name)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Raise an error is a simple value is passed to a key-value API.
|
||||
--
|
||||
|
||||
function suite.keyValueRaisesError_onSimpleValue()
|
||||
api.register { name = "testapi", kind = "test", keyed = true, scope = "project" }
|
||||
local sln = solution "MySolution"
|
||||
ok, err = pcall(function ()
|
||||
testapi "test"
|
||||
end)
|
||||
test.isfalse(ok)
|
||||
end
|
||||
|
@ -8,6 +8,7 @@
|
||||
local suite = T.configset
|
||||
|
||||
local configset = premake.configset
|
||||
local field = premake.field
|
||||
|
||||
|
||||
--
|
||||
@ -36,7 +37,7 @@
|
||||
--
|
||||
|
||||
function suite.defaultValue_onString()
|
||||
test.isnil(configset.fetchvalue(cset, "targetextension", {}))
|
||||
test.isnil(configset.fetch(cset, field.get("targetextension"), {}))
|
||||
end
|
||||
|
||||
|
||||
@ -47,7 +48,7 @@
|
||||
|
||||
function suite.canRoundtrip_onDefaultBlock()
|
||||
configset.addvalue(cset, "targetextension", ".so")
|
||||
test.isequal(".so", configset.fetchvalue(cset, "targetextension", {}))
|
||||
test.isequal(".so", configset.fetch(cset, field.get("targetextension"), {}))
|
||||
end
|
||||
|
||||
|
||||
@ -59,7 +60,7 @@
|
||||
function suite.canRoundtrip_onSimpleTermMatch()
|
||||
configset.addblock(cset, { "Windows" })
|
||||
configset.addvalue(cset, "targetextension", ".dll")
|
||||
test.isequal(".dll", configset.fetchvalue(cset, "targetextension", { "windows" }))
|
||||
test.isequal(".dll", configset.fetch(cset, field.get("targetextension"), { "windows" }))
|
||||
end
|
||||
|
||||
|
||||
@ -72,7 +73,7 @@
|
||||
configset.addvalue(cset, "targetextension", ".so")
|
||||
configset.addblock(cset, { "Windows" })
|
||||
configset.addvalue(cset, "targetextension", ".dll")
|
||||
test.isequal(".so", configset.fetchvalue(cset, "targetextension", { "linux" }))
|
||||
test.isequal(".so", configset.fetch(cset, field.get("targetextension"), { "linux" }))
|
||||
end
|
||||
|
||||
|
||||
@ -82,7 +83,7 @@
|
||||
|
||||
function suite.canRoundtrip_fromParentToChild()
|
||||
configset.addvalue(parentset, "targetextension", ".so")
|
||||
test.isequal(".so", configset.fetchvalue(cset, "targetextension", {}))
|
||||
test.isequal(".so", configset.fetch(cset, field.get("targetextension"), {}))
|
||||
end
|
||||
|
||||
|
||||
@ -93,7 +94,7 @@
|
||||
function suite.child_canOverrideStringValueFromParent()
|
||||
configset.addvalue(parentset, "targetextension", ".so")
|
||||
configset.addvalue(cset, "targetextension", ".dll")
|
||||
test.isequal(".dll", configset.fetchvalue(cset, "targetextension", {}))
|
||||
test.isequal(".dll", configset.fetch(cset, field.get("targetextension"), {}))
|
||||
end
|
||||
|
||||
|
||||
@ -105,7 +106,7 @@
|
||||
function suite.filenameMadeRelative_onBaseDirSet()
|
||||
configset.addblock(cset, { "hello.c" }, os.getcwd())
|
||||
configset.addvalue(cset, "buildaction", "copy")
|
||||
test.isequal("copy", configset.fetchvalue(cset, "buildaction", {}, path.join(os.getcwd(), "hello.c")))
|
||||
test.isequal("copy", configset.fetch(cset, field.get("buildaction"), {}, path.join(os.getcwd(), "hello.c")))
|
||||
end
|
||||
|
||||
|
||||
@ -114,7 +115,7 @@
|
||||
--
|
||||
|
||||
function suite.lists_returnsEmptyTable_onNotSet()
|
||||
test.isequal({}, configset.fetchvalue(cset, "buildoptions", {}))
|
||||
test.isequal({}, configset.fetch(cset, field.get("buildoptions"), {}))
|
||||
end
|
||||
|
||||
|
||||
@ -126,7 +127,7 @@
|
||||
configset.addvalue(cset, "buildoptions", "v1")
|
||||
configset.addblock(cset, { "windows" })
|
||||
configset.addvalue(cset, "buildoptions", "v2")
|
||||
test.isequal({"v1", "v2"}, configset.fetchvalue(cset, "buildoptions", {"windows"}))
|
||||
test.isequal({"v1", "v2"}, configset.fetch(cset, field.get("buildoptions"), {"windows"}))
|
||||
end
|
||||
|
||||
|
||||
@ -137,7 +138,7 @@
|
||||
function suite.lists_mergeValues_onAdd()
|
||||
configset.addvalue(cset, "buildoptions", "v1")
|
||||
configset.addvalue(cset, "buildoptions", "v2")
|
||||
test.isequal({"v1", "v2"}, configset.fetchvalue(cset, "buildoptions", {"windows"}))
|
||||
test.isequal({"v1", "v2"}, configset.fetch(cset, field.get("buildoptions"), {"windows"}))
|
||||
end
|
||||
|
||||
|
||||
@ -147,7 +148,7 @@
|
||||
|
||||
function suite.lists_includeValueKeys()
|
||||
configset.addvalue(cset, "buildoptions", { "v1", "v2" })
|
||||
local x = configset.fetchvalue(cset, "buildoptions", {})
|
||||
local x = configset.fetch(cset, field.get("buildoptions"), {})
|
||||
test.isequal("v2", x.v2)
|
||||
end
|
||||
|
||||
@ -159,13 +160,13 @@
|
||||
function suite.remove_onExactValueMatch()
|
||||
configset.addvalue(cset, "flags", { "Symbols", "Unsafe", "NoRTTI" })
|
||||
configset.removevalues(cset, "flags", { "Unsafe" })
|
||||
test.isequal({ "Symbols", "NoRTTI" }, configset.fetchvalue(cset, "flags", {}))
|
||||
test.isequal({ "Symbols", "NoRTTI" }, configset.fetch(cset, field.get("flags"), {}))
|
||||
end
|
||||
|
||||
function suite.remove_onMultipleValues()
|
||||
configset.addvalue(cset, "flags", { "Symbols", "NoExceptions", "Unsafe", "NoRTTI" })
|
||||
configset.removevalues(cset, "flags", { "NoExceptions", "NoRTTI" })
|
||||
test.isequal({ "Symbols", "Unsafe" }, configset.fetchvalue(cset, "flags", {}))
|
||||
test.isequal({ "Symbols", "Unsafe" }, configset.fetch(cset, field.get("flags"), {}))
|
||||
end
|
||||
|
||||
|
||||
@ -176,7 +177,7 @@
|
||||
function suite.remove_onWildcard()
|
||||
configset.addvalue(cset, "defines", { "WIN32", "WIN64", "LINUX", "MACOSX" })
|
||||
configset.removevalues(cset, "defines", { "WIN*" })
|
||||
test.isequal({ "LINUX", "MACOSX" }, configset.fetchvalue(cset, "defines", {}))
|
||||
test.isequal({ "LINUX", "MACOSX" }, configset.fetch(cset, field.get("defines"), {}))
|
||||
end
|
||||
|
||||
|
||||
@ -188,7 +189,7 @@
|
||||
configset.addvalue(cset, "configmap", { Debug="Debug", Release="Release" })
|
||||
configset.addblock(cset, { "windows" })
|
||||
configset.addvalue(cset, "configmap", { Profile="Profile" })
|
||||
local x = configset.fetchvalue(cset, "configmap", {"windows"})
|
||||
local x = configset.fetch(cset, field.get("configmap"), {"windows"})
|
||||
test.istrue(x.Debug and x.Release and x.Profile)
|
||||
end
|
||||
|
||||
@ -200,7 +201,7 @@
|
||||
function suite.keyed_mergesKeys_onAdd()
|
||||
configset.addvalue(cset, "configmap", { Debug="Debug", Release="Release" })
|
||||
configset.addvalue(cset, "configmap", { Profile="Profile" })
|
||||
local x = configset.fetchvalue(cset, "configmap", {"windows"})
|
||||
local x = configset.fetch(cset, field.get("configmap"), {"windows"})
|
||||
test.istrue(x.Debug and x.Release and x.Profile)
|
||||
end
|
||||
|
||||
@ -213,14 +214,14 @@
|
||||
configset.addvalue(cset, "configmap", { Debug="Debug" })
|
||||
configset.addblock(cset, { "windows" })
|
||||
configset.addvalue(cset, "configmap", { Debug="Development" })
|
||||
local x = configset.fetchvalue(cset, "configmap", {"windows"})
|
||||
local x = configset.fetch(cset, field.get("configmap"), {"windows"})
|
||||
test.isequal("Development", x.Debug)
|
||||
end
|
||||
|
||||
function suite.keyed_overwritesValues_onNonMergeAdd()
|
||||
configset.addvalue(cset, "configmap", { Debug="Debug" })
|
||||
configset.addvalue(cset, "configmap", { Debug="Development" })
|
||||
local x = configset.fetchvalue(cset, "configmap", {"windows"})
|
||||
local x = configset.fetch(cset, field.get("configmap"), {"windows"})
|
||||
test.isequal("Development", x.Debug)
|
||||
end
|
||||
|
||||
@ -233,13 +234,13 @@
|
||||
configset.addvalue(cset, "vpaths", { includes="*.h" })
|
||||
configset.addblock(cset, { "windows" })
|
||||
configset.addvalue(cset, "vpaths", { includes="*.hpp" })
|
||||
local x = configset.fetchvalue(cset, "vpaths", {"windows"})
|
||||
local x = configset.fetch(cset, field.get("vpaths"), {"windows"})
|
||||
test.isequal({ "*.h", "*.hpp" }, x.includes)
|
||||
end
|
||||
|
||||
function suite.keyed_mergesValues_onMergeAdd()
|
||||
configset.addvalue(cset, "vpaths", { includes="*.h" })
|
||||
configset.addvalue(cset, "vpaths", { includes="*.hpp" })
|
||||
local x = configset.fetchvalue(cset, "vpaths", {"windows"})
|
||||
local x = configset.fetch(cset, field.get("vpaths"), {"windows"})
|
||||
test.isequal({ "*.h", "*.hpp" }, x.includes)
|
||||
end
|
||||
|
@ -84,7 +84,6 @@
|
||||
dofile("oven/test_filtering.lua")
|
||||
|
||||
-- API tests
|
||||
dofile("api/test_callback.lua")
|
||||
dofile("api/test_containers.lua")
|
||||
dofile("api/test_directory_kind.lua")
|
||||
dofile("api/test_list_kind.lua")
|
||||
|
Reference in New Issue
Block a user