diff --git a/src/base/validation.lua b/src/base/validation.lua index fe1758ce..f2729f1a 100644 --- a/src/base/validation.lua +++ b/src/base/validation.lua @@ -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