Commits

Jason Perkins  committed 145553e

Added new array API value type, and started support for new key-value handling

  • Participants
  • Parent commits 6ff7cd5

Comments (0)

Files changed (5)

File src/base/api.lua

 -- for usage examples.
 --
 
-	function api.register(description)
+	function api.register(field)
 		-- verify the name
-		local name = description.name
+		local name = field.name
 		if not name then
 			error("missing name", 2)
 		end
 		end
 
 		-- make sure there is a handler available for this kind of value
-		if not api["set" .. description.kind] then
-			error("invalid kind", 2)
+		local kind = field.kind
+		if kind:startswith("key-") then
+			kind = kind:sub(5)
+		end
+		
+		if not api["set" .. kind] then
+			error("invalid kind '" .. kind .. "'", 2)
 		end
 		
 		_G[name] = function(value)
-			return api.callback(description, value)
+			return api.callback(field, value)
 		end
 	end
 
 			error("no " .. field.scope .. " in scope", 3)
 		end
 		
-		-- find and call the setter for this field's value kind
-		local setter = api["set" .. field.kind]
-		setter(target, field, value)
+		-- A keyed value is a table containing key-value pairs, where the
+		-- type of the value is defined by the field. 
+		if field.kind:startswith("key-") then		
+			target[field.name] = target[field.name] or {}
+			api.setkeyvalue(target[field.name], field, value)
+			
+		-- Otherwise, it is a "simple" value defined by the field
+		else
+			local setter = api["set" .. field.kind]
+			setter(target, field.name, field, value)
+		end
+	end
+
+
+--
+-- Update a keyed value. Iterate over the keys in the new value, and use
+-- the corresponding values to update the target object.
+--
+
+	function api.setkeyvalue(target, field, values)
+		if type(values) ~= "table" then
+			error("value must be a table of key-value pairs", 4)
+		end
+		
+		local kind = field.kind:sub(5)
+		local setter = api["set" .. kind]
+		for key, value in pairs(values) do
+			setter(target, key, field, value)
+		end
+	end
+
+
+--
+-- Set a new array value. Arrays are lists of values stored by "value",
+-- in that new values overwrite old ones, rather than merging like lists.
+--
+
+	function api.setarray(target, name, field, value)
+		-- put simple values in an array
+		if type(value) ~= "table" then
+			value = { value }
+		end
+		
+		-- store it, overwriting any existing value
+		target[field.name] = value
 	end
 
 
 -- Set a new string value on an API field.
 --
 
-	function api.setstring(target, field, value)
+	function api.setstring(target, name, field, value)
+		error("setstring is not yet implemented")
 	end
 
 

File tests/api/test_array_kind.lua

+--
+-- tests/api/test_array_kind.lua
+-- Tests the array API value type.
+-- Copyright (c) 2012 Jason Perkins and the Premake project
+--
+
+	T.api_array_kind = {}
+	local suite = T.api_array_kind
+	local api = premake.api
+
+
+--
+-- Setup and teardown
+--
+
+	function suite.setup()
+		api.register { name = "testapi", kind = "array", scope = "project" }
+		test.createsolution()
+	end
+
+	function suite.teardown()
+		testapi = nil
+	end
+
+
+--
+-- Array values should be stored as-is.
+--
+
+	function suite.storesTable_onArrayValue()
+		testapi { "one", "two" }
+		test.isequal({ "one", "two" }, api.scope.project.testapi)
+	end
+
+
+--
+-- String values should be converted into a table.
+--
+
+	function suite.storesTable_onStringValue()
+		testapi "myvalue"
+		test.isequal({ "myvalue" }, api.scope.project.testapi)
+	end
+

File tests/api/test_callback.lua

 --
 
 	function suite.setup()
-		api.settest = function(target, field, value) 
+		api.settest = function(target, name, field, value) 
 			test_args = {
 				["target"] = target,
+				["name"] = name,
 				["field"] = field,
 				["value"] = value
 			}
 
 
 	function suite.teardown()
-		_G["testapi"] = nil
+		testapi = nil
 		test_args = nil
 		api.settest = nil
 	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.
 --
 
 		testapi "test"
 		test.istrue(cfg == test_args.target)
 	end
+
+
+--
+-- On key-value APIs, the keyed object value should be the target.
+--
+
+	function suite.keyObjectTarget_onKeyValue()
+		api.register { name = "testapi", kind = "key-test", scope = "project" }
+		local sln = solution "MySolution"
+		testapi { key = "test" }
+		test.istrue(sln.testapi == 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 = "key-test", 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 = "key-test", scope = "project" }
+		local sln = solution "MySolution"
+		ok, err = pcall(function () 
+			testapi "test"
+		end)
+		test.isfalse(ok)
+	end
+

File tests/api/test_register.lua

 -- Setup and teardown
 --
 
-	local callback_args
-	
-	function suite.setup()
-		suite.callback = api.callback
-		api.callback = function(...) callback_args = arg end
-	end
-
-
 	function suite.teardown()
-		_G["testapi"] = nil
-		api.callback = suite.callback
-		callback_args = nil
+		testapi = nil
 	end
 
 
 
 
 --
--- Verify that the central API callback is invoked by the registered function.
+-- Verify that key-value forms are accepted.
 --
 
-	function suite.callbackInvoked_onApiCall()
-		api.register { name = "testapi", kind = "testkind", scope = "project" }
-		testapi "testvalue"
-		test.isnotnil(callback_args)
+	function suite.succeeds_onKeyValueForm()
+		ok, err = pcall(function () 
+			api.register { name = "testapi", kind = "key-string", scope = "project" }
+		end)				
+		test.istrue(ok)
 	end

File tests/premake4.lua

 	dofile("config/test_targetinfo.lua")
 
 	-- API tests
+	dofile("api/test_array_kind.lua")
 	dofile("api/test_callback.lua")
 	dofile("api/test_register.lua")