Relax module naming restrictions

Forcing module names to be valid ninja names is an unnecessary
restraint on the project build logic.  Allow any string as a
module name, and sanitize and uniquify the module name for use
in module-scoped variables.

Also move the module scope to be per-module instead of per-group
so that modules can use the same local variable name for each variant.

Change-Id: If44cca20712305e2c0b6d6b39daa5eace335c148
This commit is contained in:
Colin Cross 2015-02-10 11:26:26 -08:00
parent 50fb09375a
commit 6134a5c66a
3 changed files with 48 additions and 22 deletions

View file

@ -26,6 +26,7 @@ import (
"reflect" "reflect"
"runtime" "runtime"
"sort" "sort"
"strconv"
"strings" "strings"
"text/scanner" "text/scanner"
"text/template" "text/template"
@ -67,6 +68,7 @@ type Context struct {
moduleGroupsSorted []*moduleGroup moduleGroupsSorted []*moduleGroup
singletonInfo map[string]*singletonInfo singletonInfo map[string]*singletonInfo
mutatorInfo []*mutatorInfo mutatorInfo []*mutatorInfo
moduleNinjaNames map[string]*moduleGroup
dependenciesReady bool // set to true on a successful ResolveDependencies dependenciesReady bool // set to true on a successful ResolveDependencies
buildActionsReady bool // set to true on a successful PrepareBuildActions buildActionsReady bool // set to true on a successful PrepareBuildActions
@ -106,6 +108,7 @@ type localBuildActions struct {
type moduleGroup struct { type moduleGroup struct {
// set during Parse // set during Parse
typeName string typeName string
ninjaName string
relBlueprintsFile string relBlueprintsFile string
pos scanner.Position pos scanner.Position
propertyPos map[string]scanner.Position propertyPos map[string]scanner.Position
@ -186,6 +189,7 @@ func NewContext() *Context {
moduleGroups: make(map[string]*moduleGroup), moduleGroups: make(map[string]*moduleGroup),
moduleInfo: make(map[Module]*moduleInfo), moduleInfo: make(map[Module]*moduleInfo),
singletonInfo: make(map[string]*singletonInfo), singletonInfo: make(map[string]*singletonInfo),
moduleNinjaNames: make(map[string]*moduleGroup),
} }
} }
@ -790,23 +794,23 @@ func (c *Context) processModuleDef(moduleDef *parser.Module,
return nil, errs return nil, errs
} }
ninjaName := toNinjaName(group.properties.Name)
// The sanitizing in toNinjaName can result in collisions, uniquify the name if it
// already exists
for i := 0; c.moduleNinjaNames[ninjaName] != nil; i++ {
ninjaName = toNinjaName(group.properties.Name) + strconv.Itoa(i)
}
c.moduleNinjaNames[ninjaName] = group
group.ninjaName = ninjaName
group.pos = moduleDef.Type.Pos group.pos = moduleDef.Type.Pos
group.propertyPos = make(map[string]scanner.Position) group.propertyPos = make(map[string]scanner.Position)
for name, propertyDef := range propertyMap { for name, propertyDef := range propertyMap {
group.propertyPos[name] = propertyDef.Pos group.propertyPos[name] = propertyDef.Pos
} }
name := group.properties.Name
err := validateNinjaName(name)
if err != nil {
return nil, []error{
&Error{
Err: fmt.Errorf("invalid module name %q: %s", err),
Pos: group.propertyPos["name"],
},
}
}
module := &moduleInfo{ module := &moduleInfo{
group: group, group: group,
logicModule: logicModule, logicModule: logicModule,
@ -1317,12 +1321,13 @@ func (c *Context) generateModuleBuildActions(config interface{},
}() }()
c.parallelVisitAllBottomUp(func(group *moduleGroup) bool { c.parallelVisitAllBottomUp(func(group *moduleGroup) bool {
for _, module := range group.modules {
// The parent scope of the moduleContext's local scope gets overridden to be that of the // The parent scope of the moduleContext's local scope gets overridden to be that of the
// calling Go package on a per-call basis. Since the initial parent scope doesn't matter we // calling Go package on a per-call basis. Since the initial parent scope doesn't matter we
// just set it to nil. // just set it to nil.
scope := newLocalScope(nil, moduleNamespacePrefix(group.properties.Name)) prefix := moduleNamespacePrefix(group.ninjaName + "_" + module.subName())
scope := newLocalScope(nil, prefix)
for _, module := range group.modules {
mctx := &moduleContext{ mctx := &moduleContext{
baseModuleContext: baseModuleContext{ baseModuleContext: baseModuleContext{
context: c, context: c,

View file

@ -15,6 +15,7 @@
package blueprint package blueprint
import ( import (
"bytes"
"fmt" "fmt"
"strings" "strings"
) )
@ -288,6 +289,26 @@ func validateNinjaName(name string) error {
return nil return nil
} }
func toNinjaName(name string) string {
ret := bytes.Buffer{}
ret.Grow(len(name))
for _, r := range name {
valid := (r >= 'a' && r <= 'z') ||
(r >= 'A' && r <= 'Z') ||
(r >= '0' && r <= '9') ||
(r == '_') ||
(r == '-') ||
(r == '.')
if valid {
ret.WriteRune(r)
} else {
ret.WriteRune('_')
}
}
return ret.String()
}
var builtinRuleArgs = []string{"out", "in"} var builtinRuleArgs = []string{"out", "in"}
func validateArgName(argName string) error { func validateArgName(argName string) error {