Split validation checks into individual tests and call arrays

This commit is contained in:
Jason Perkins 2015-12-28 18:27:06 -05:00
parent c74e8d12ee
commit 4102c9dd7f

View File

@ -4,18 +4,28 @@
-- Verify the contents of the project object before handing them off to
-- the action/exporter.
--
-- Copyright (c) 2002-2014 Jason Perkins and the Premake project
-- Copyright (c) 2002-2015 Jason Perkins and the Premake project
---
premake.validation = {}
local m = premake.validation
local p = premake
m.elements = {}
---
-- Validate the global container and all of its contents.
---
m.elements.global = function(glb)
return {
}
end
function p.global.validate(self)
p.callArray(m.elements.global, self)
p.container.validateChildren(self)
end
@ -25,21 +35,15 @@
-- Validate a workspace and its projects.
---
m.elements.workspace = function(wks)
return {
m.workspaceHasConfigs,
m.uniqueProjectIds,
}
end
function p.workspace.validate(self)
-- there must be at least one build configuration
if not self.configurations or #self.configurations == 0 then
p.error("workspace '%s' does not contain any configurations", self.name)
end
-- all project UUIDs must be unique
local uuids = {}
for prj in p.workspace.eachproject(self) do
if uuids[prj.uuid] then
p.error("projects '%s' and '%s' have the same UUID", uuids[prj.uuid], prj.name)
end
uuids[prj.uuid] = prj.name
end
p.callArray(m.elements.workspace, self)
p.container.validateChildren(self)
end
@ -49,31 +53,18 @@
-- Validate a project and its configurations.
---
m.elements.project = function(prj)
return {
m.projectHasLanguage,
m.actionSupportsLanguage,
m.actionSupportsKind,
m.projectRulesExist,
m.projectValuesInScope,
}
end
function p.project.validate(self)
-- must have a language
if not self.language then
p.error("project '%s' does not have a language", self.name)
end
if not p.action.supports(self.language) then
p.warn("unsupported language '%s' used for project '%s'", self.language, self.name)
end
if not p.action.supports(self.kind) then
p.warn("unsupported kind '%s' used for project '%s'", self.kind, self.name)
end
-- all rules must exist
for i = 1, #self.rules do
local rule = self.rules[i]
if not p.global.getRule(rule) then
p.error("project '%s' uses missing rule '%s'", self.name, rule)
end
end
-- check for out of scope fields
p.config.validateScopes(self, self, "project")
p.callArray(m.elements.project, self)
for cfg in p.project.eachconfig(self) do
p.config.validate(cfg)
end
@ -85,20 +76,33 @@
-- Validate a project configuration.
---
m.elements.config = function(cfg)
return {
m.configHasKind,
m.configSupportsKind,
m.configValuesInScope,
}
end
function p.config.validate(self)
-- must have a kind
if not self.kind then
p.error("project '%s' needs a kind in configuration '%s'", self.project.name, self.name)
end
p.callArray(m.elements.config, self)
-- makefile configuration can only appear in C++ projects; this is the
-- default now, so should only be a problem if overridden.
if (self.kind == p.MAKEFILE or self.kind == p.NONE) and not p.project.iscpp(self.project) then
p.error("project '%s' uses %s kind in configuration '%s'; language must be C++", self.project.name, self.kind, self.name)
end
end
-- check for out of scope fields
p.config.validateScopes(self, self.project, "config")
---
-- Validate a rule.
---
m.elements.rule = function(rule)
return {
-- TODO: fill this in
}
end
function p.rule.validate(self)
p.callArray(m.elements.rule, self)
end
@ -151,11 +155,82 @@
---
-- Validate a rule.
---
---------------------------------------------------------------------------
--
-- Handlers for individual checks
--
---------------------------------------------------------------------------
function p.rule.validate(self)
-- TODO: fill this in
function m.actionSupportsKind(prj)
if not p.action.supports(prj.kind) then
p.warn("unsupported kind '%s' used for project '%s'", prj.kind, prj.name)
end
end
function m.actionSupportsLanguage(prj)
if not p.action.supports(prj.language) then
p.warn("unsupported language '%s' used for project '%s'", prj.language, prj.name)
end
end
function m.configHasKind(cfg)
if not cfg.kind then
p.error("project '%s' needs a kind in configuration '%s'", cfg.project.name, cfg.name)
end
end
function m.configSupportsKind(cfg)
-- makefile configuration can only appear in C++ projects; this is the
-- default now, so should only be a problem if overridden.
if (cfg.kind == p.MAKEFILE or cfg.kind == p.NONE) and not p.project.iscpp(cfg.project) then
p.error("project '%s' uses %s kind in configuration '%s'; language must be C++", cfg.project.name, cfg.kind, cfg.name)
end
end
function m.configValuesInScope(cfg)
p.config.validateScopes(cfg, cfg.project, "config")
end
function m.projectHasLanguage(prj)
if not prj.language then
p.error("project '%s' does not have a language", prj.name)
end
end
function m.projectRulesExist(prj)
for i = 1, #prj.rules do
local rule = prj.rules[i]
if not p.global.getRule(rule) then
p.error("project '%s' uses missing rule '%s'", prj.name, rule)
end
end
end
function m.projectValuesInScope(prj)
p.config.validateScopes(prj, prj, "project")
end
function m.uniqueProjectIds(wks)
local uuids = {}
for prj in p.workspace.eachproject(wks) do
if uuids[prj.uuid] then
p.error("projects '%s' and '%s' have the same UUID", uuids[prj.uuid], prj.name)
end
uuids[prj.uuid] = prj.name
end
end
function m.workspaceHasConfigs(wks)
if not wks.configurations or #wks.configurations == 0 then
p.error("workspace '%s' does not contain any configurations", wks.name)
end
end