Merge remote-tracking branch 'aosp/upstream' into master

* aosp/upstream:
  Extract module naming into an interface

Bug: 65683273
Test: build/soong/scripts/diff_build_graphs.sh \
      --products=aosp_arm \
      'build/blueprint:work^ build/soong:work^' \
      'build/blueprint:work build/soong:work'
      # and see that the only changes were:
      # 1. adding some new files
      # 2. changing some line numbers
Test: m -j nothing # which runs unit tests

Change-Id: I2a2f958579fc6f96fad0eb06a5f98c93b80459b3
diff --git a/Blueprints b/Blueprints
index edda8b8..de18298 100644
--- a/Blueprints
+++ b/Blueprints
@@ -12,6 +12,7 @@
         "live_tracker.go",
         "mangle.go",
         "module_ctx.go",
+        "name_interface.go",
         "ninja_defs.go",
         "ninja_strings.go",
         "ninja_writer.go",
diff --git a/context.go b/context.go
index ab5efee..11bfa50 100644
--- a/context.go
+++ b/context.go
@@ -69,7 +69,7 @@
 type Context struct {
 	// set at instantiation
 	moduleFactories     map[string]ModuleFactory
-	moduleNames         map[string]*moduleGroup
+	nameInterface       NameInterface
 	moduleGroups        []*moduleGroup
 	moduleInfo          map[Module]*moduleInfo
 	modulesSorted       []*moduleInfo
@@ -104,8 +104,8 @@
 	requiredNinjaMinor int          // For the ninja_required_version variable
 	requiredNinjaMicro int          // For the ninja_required_version variable
 
-	// set lazily by sortedModuleNames
-	cachedSortedModuleNames []string
+	// set lazily by sortedModuleGroups
+	cachedSortedModuleGroups []*moduleGroup
 
 	globs    map[string]GlobPath
 	globLock sync.Mutex
@@ -158,6 +158,8 @@
 	ninjaName string
 
 	modules []*moduleInfo
+
+	namespace Namespace
 }
 
 type moduleInfo struct {
@@ -211,6 +213,10 @@
 	return s
 }
 
+func (module *moduleInfo) namespace() Namespace {
+	return module.group.namespace
+}
+
 // A Variation is a way that a variant of a module differs from other variants of the same module.
 // For example, two variants of the same module might have Variation{"arch","arm"} and
 // Variation{"arch","arm64"}
@@ -270,7 +276,7 @@
 func newContext() *Context {
 	return &Context{
 		moduleFactories:    make(map[string]ModuleFactory),
-		moduleNames:        make(map[string]*moduleGroup),
+		nameInterface:      NewSimpleNameInterface(),
 		moduleInfo:         make(map[Module]*moduleInfo),
 		moduleNinjaNames:   make(map[string]*moduleGroup),
 		globs:              make(map[string]GlobPath),
@@ -416,6 +422,10 @@
 	})
 }
 
+func (c *Context) SetNameInterface(i NameInterface) {
+	c.nameInterface = i
+}
+
 func singletonPkgPath(singleton Singleton) string {
 	typ := reflect.TypeOf(singleton)
 	for typ.Kind() == reflect.Ptr {
@@ -1233,21 +1243,7 @@
 	name := module.logicModule.Name()
 	c.moduleInfo[module.logicModule] = module
 
-	if group, present := c.moduleNames[name]; present {
-		return []error{
-			&BlueprintError{
-				Err: fmt.Errorf("module %q already defined", name),
-				Pos: module.pos,
-			},
-			&BlueprintError{
-				Err: fmt.Errorf("<-- previous definition here"),
-				Pos: group.modules[0].pos,
-			},
-		}
-	}
-
 	ninjaName := toNinjaName(name)
-
 	// The sanitizing in toNinjaName can result in collisions, uniquify the name if it
 	// already exists
 	for i := 0; c.moduleNinjaNames[ninjaName] != nil; i++ {
@@ -1260,7 +1256,18 @@
 		modules:   []*moduleInfo{module},
 	}
 	module.group = group
-	c.moduleNames[name] = group
+	namespace, errs := c.nameInterface.NewModule(
+		&moduleCreationContextImpl{c.ModuleDir(module.logicModule)},
+		ModuleGroup{moduleGroup: group},
+		module.logicModule)
+	if len(errs) > 0 {
+		for i := range errs {
+			errs[i] = &BlueprintError{Err: errs[i], Pos: module.pos}
+		}
+		return errs
+	}
+	group.namespace = namespace
+
 	c.moduleNinjaNames[ninjaName] = group
 	c.moduleGroups = append(c.moduleGroups, group)
 
@@ -1347,17 +1354,9 @@
 		}}
 	}
 
-	possibleDeps := c.modulesFromName(depName)
+	possibleDeps := c.modulesFromName(depName, module.namespace())
 	if possibleDeps == nil {
-		if c.allowMissingDependencies {
-			module.missingDeps = append(module.missingDeps, depName)
-			return nil
-		}
-		return []error{&BlueprintError{
-			Err: fmt.Errorf("%q depends on undefined module %q",
-				module.Name(), depName),
-			Pos: module.pos,
-		}}
+		return c.discoveredMissingDependencies(module, depName)
 	}
 
 	if m := c.findMatchingVariant(module, possibleDeps); m != nil {
@@ -1395,7 +1394,7 @@
 		}}
 	}
 
-	possibleDeps := c.modulesFromName(destName)
+	possibleDeps := c.modulesFromName(destName, module.namespace())
 	if possibleDeps == nil {
 		return nil, []error{&BlueprintError{
 			Err: fmt.Errorf("%q has a reverse dependency on undefined module %q",
@@ -1429,17 +1428,9 @@
 		panic("BaseDependencyTag is not allowed to be used directly!")
 	}
 
-	possibleDeps := c.modulesFromName(depName)
+	possibleDeps := c.modulesFromName(depName, module.namespace())
 	if possibleDeps == nil {
-		if c.allowMissingDependencies {
-			module.missingDeps = append(module.missingDeps, depName)
-			return nil
-		}
-		return []error{&BlueprintError{
-			Err: fmt.Errorf("%q depends on undefined module %q",
-				module.Name(), depName),
-			Pos: module.pos,
-		}}
+		return c.discoveredMissingDependencies(module, depName)
 	}
 
 	// We can't just append variant.Variant to module.dependencyVariants.variantName and
@@ -2190,11 +2181,7 @@
 		if module.missingDeps != nil && !mctx.handledMissingDeps {
 			var errs []error
 			for _, depName := range module.missingDeps {
-				errs = append(errs, &BlueprintError{
-					Err: fmt.Errorf("%q depends on undefined module %q",
-						module.Name(), depName),
-					Pos: module.pos,
-				})
+				errs = append(errs, c.missingDependencyError(module, depName))
 			}
 			errsCh <- errs
 			return true
@@ -2359,7 +2346,7 @@
 }
 
 func (c *Context) moduleMatchingVariant(module *moduleInfo, name string) *moduleInfo {
-	targets := c.modulesFromName(name)
+	targets := c.modulesFromName(name, module.namespace())
 
 	if targets == nil {
 		return nil
@@ -2378,29 +2365,11 @@
 	var errs []error
 	for _, rename := range renames {
 		group, name := rename.group, rename.name
-		if name == group.name {
+		if name == group.name || len(group.modules) < 1 {
 			continue
 		}
 
-		existing := c.moduleNames[name]
-		if existing != nil {
-			errs = append(errs,
-				&BlueprintError{
-					Err: fmt.Errorf("renaming module %q to %q conflicts with existing module",
-						group.name, name),
-					Pos: group.modules[0].pos,
-				},
-				&BlueprintError{
-					Err: fmt.Errorf("<-- existing module defined here"),
-					Pos: existing.modules[0].pos,
-				},
-			)
-			continue
-		}
-
-		c.moduleNames[name] = group
-		delete(c.moduleNames, group.name)
-		group.name = name
+		errs = append(errs, c.nameInterface.Rename(group.name, rename.name, group.namespace)...)
 	}
 
 	return errs
@@ -2423,24 +2392,45 @@
 	return errs
 }
 
-func (c *Context) modulesFromName(name string) []*moduleInfo {
-	if group := c.moduleNames[name]; group != nil {
+func (c *Context) discoveredMissingDependencies(module *moduleInfo, depName string) (errs []error) {
+	if c.allowMissingDependencies {
+		module.missingDeps = append(module.missingDeps, depName)
+		return nil
+	}
+	return []error{c.missingDependencyError(module, depName)}
+}
+
+func (c *Context) missingDependencyError(module *moduleInfo, depName string) (errs error) {
+	err := c.nameInterface.MissingDependencyError(module.Name(), module.namespace(), depName)
+
+	return &BlueprintError{
+		Err: err,
+		Pos: module.pos,
+	}
+}
+
+func (c *Context) modulesFromName(name string, namespace Namespace) []*moduleInfo {
+	group, exists := c.nameInterface.ModuleFromName(name, namespace)
+	if exists {
 		return group.modules
 	}
 	return nil
 }
 
-func (c *Context) sortedModuleNames() []string {
-	if c.cachedSortedModuleNames == nil {
-		c.cachedSortedModuleNames = make([]string, 0, len(c.moduleNames))
-		for moduleName := range c.moduleNames {
-			c.cachedSortedModuleNames = append(c.cachedSortedModuleNames,
-				moduleName)
+func (c *Context) sortedModuleGroups() []*moduleGroup {
+	if c.cachedSortedModuleGroups == nil {
+		unwrap := func(wrappers []ModuleGroup) []*moduleGroup {
+			result := make([]*moduleGroup, 0, len(wrappers))
+			for _, group := range wrappers {
+				result = append(result, group.moduleGroup)
+			}
+			return result
 		}
-		sort.Strings(c.cachedSortedModuleNames)
+
+		c.cachedSortedModuleGroups = unwrap(c.nameInterface.AllModules())
 	}
 
-	return c.cachedSortedModuleNames
+	return c.cachedSortedModuleGroups
 }
 
 func (c *Context) visitAllModules(visit func(Module)) {
@@ -2453,9 +2443,8 @@
 		}
 	}()
 
-	for _, moduleName := range c.sortedModuleNames() {
-		modules := c.modulesFromName(moduleName)
-		for _, module = range modules {
+	for _, moduleGroup := range c.sortedModuleGroups() {
+		for _, module = range moduleGroup.modules {
 			visit(module.logicModule)
 		}
 	}
@@ -2473,9 +2462,8 @@
 		}
 	}()
 
-	for _, moduleName := range c.sortedModuleNames() {
-		modules := c.modulesFromName(moduleName)
-		for _, module := range modules {
+	for _, moduleGroup := range c.sortedModuleGroups() {
+		for _, module := range moduleGroup.modules {
 			if pred(module.logicModule) {
 				visit(module.logicModule)
 			}
diff --git a/context_test.go b/context_test.go
index c6bc08c..16c52cf 100644
--- a/context_test.go
+++ b/context_test.go
@@ -183,7 +183,7 @@
 
 	var outputDown string
 	var outputUp string
-	topModule := ctx.modulesFromName("A")[0]
+	topModule := ctx.modulesFromName("A", nil)[0]
 	ctx.walkDeps(topModule,
 		func(dep depInfo, parent *moduleInfo) bool {
 			if dep.module.logicModule.(Walker).Walk() {
@@ -239,10 +239,10 @@
 		t.FailNow()
 	}
 
-	a := ctx.modulesFromName("A")[0].logicModule.(*fooModule)
-	b := ctx.modulesFromName("B")[0].logicModule.(*barModule)
-	c := ctx.modulesFromName("C")[0].logicModule.(*barModule)
-	d := ctx.modulesFromName("D")[0].logicModule.(*fooModule)
+	a := ctx.modulesFromName("A", nil)[0].logicModule.(*fooModule)
+	b := ctx.modulesFromName("B", nil)[0].logicModule.(*barModule)
+	c := ctx.modulesFromName("C", nil)[0].logicModule.(*barModule)
+	d := ctx.modulesFromName("D", nil)[0].logicModule.(*fooModule)
 
 	checkDeps := func(m Module, expected string) {
 		var deps []string
diff --git a/module_ctx.go b/module_ctx.go
index 630d7a2..769c59a 100644
--- a/module_ctx.go
+++ b/module_ctx.go
@@ -142,6 +142,8 @@
 
 	moduleInfo() *moduleInfo
 	error(err error)
+
+	Namespace() Namespace
 }
 
 type DynamicDependerModuleContext BottomUpMutatorContext
@@ -269,6 +271,10 @@
 	return d.context.fs
 }
 
+func (d *baseModuleContext) Namespace() Namespace {
+	return d.context.nameInterface.GetNamespace(d)
+}
+
 var _ ModuleContext = (*moduleContext)(nil)
 
 type moduleContext struct {
@@ -650,7 +656,8 @@
 // correctly for all future mutator passes.
 func (mctx *mutatorContext) AddDependency(module Module, tag DependencyTag, deps ...string) {
 	for _, dep := range deps {
-		errs := mctx.context.addDependency(mctx.context.moduleInfo[module], tag, dep)
+		modInfo := mctx.context.moduleInfo[module]
+		errs := mctx.context.addDependency(modInfo, tag, dep)
 		if len(errs) > 0 {
 			mctx.errs = append(mctx.errs, errs...)
 		}
@@ -731,7 +738,8 @@
 }
 
 func (mctx *mutatorContext) OtherModuleExists(name string) bool {
-	return mctx.context.moduleNames[name] != nil
+	_, exists := mctx.context.nameInterface.ModuleFromName(name, mctx.module.namespace())
+	return exists
 }
 
 // Rename all variants of a module.  The new name is not visible to calls to ModuleName,
diff --git a/name_interface.go b/name_interface.go
new file mode 100644
index 0000000..b3a1566
--- /dev/null
+++ b/name_interface.go
@@ -0,0 +1,167 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package blueprint
+
+import (
+	"fmt"
+	"sort"
+)
+
+// This file exposes the logic of locating a module via a query string, to enable
+// other projects to override it if desired.
+// The default name resolution implementation, SimpleNameInterface,
+// just treats the query string as a module name, and does a simple map lookup.
+
+// A ModuleGroup just points to a moduleGroup to allow external packages to refer
+// to a moduleGroup but not use it
+type ModuleGroup struct {
+	*moduleGroup
+}
+
+func (h *ModuleGroup) String() string {
+	return h.moduleGroup.name
+}
+
+// The Namespace interface is just a marker interface for usage by the NameInterface,
+// to allow a NameInterface to specify that a certain parameter should be a Namespace.
+// In practice, a specific NameInterface will expect to only give and receive structs of
+// the same concrete type, but because Go doesn't support generics, we use a marker interface
+// for a little bit of clarity, and expect implementers to do typecasting instead.
+type Namespace interface {
+	namespace(Namespace)
+}
+type NamespaceMarker struct {
+}
+
+func (m *NamespaceMarker) namespace(Namespace) {
+}
+
+// A NameInterface tells how to locate modules by name.
+// There should only be one name interface per Context, but potentially many namespaces
+type NameInterface interface {
+	// Gets called when a new module is created
+	NewModule(ctx NamespaceContext, group ModuleGroup, module Module) (namespace Namespace, err []error)
+
+	// Finds the module with the given name
+	ModuleFromName(moduleName string, namespace Namespace) (group ModuleGroup, found bool)
+
+	// Returns an error indicating that the given module could not be found.
+	// The error contains some diagnostic information about where the dependency can be found.
+	MissingDependencyError(depender string, dependerNamespace Namespace, depName string) (err error)
+
+	// Rename
+	Rename(oldName string, newName string, namespace Namespace) []error
+
+	// Returns all modules in a deterministic order.
+	AllModules() []ModuleGroup
+
+	// gets the namespace for a given path
+	GetNamespace(ctx NamespaceContext) (namespace Namespace)
+}
+
+// A NamespaceContext stores the information given to a NameInterface to enable the NameInterface
+// to choose the namespace for any given module
+type NamespaceContext interface {
+	ModuleDir() string
+}
+
+type moduleCreationContextImpl struct {
+	moduleDir string
+}
+
+func (ctx *moduleCreationContextImpl) ModuleDir() string {
+	return ctx.moduleDir
+}
+
+// a SimpleNameInterface just stores all modules in a map based on name
+type SimpleNameInterface struct {
+	modules map[string]ModuleGroup
+}
+
+func NewSimpleNameInterface() *SimpleNameInterface {
+	return &SimpleNameInterface{
+		modules: make(map[string]ModuleGroup),
+	}
+}
+
+func (s *SimpleNameInterface) NewModule(ctx NamespaceContext, group ModuleGroup, module Module) (namespace Namespace, err []error) {
+	name := group.name
+	if group, present := s.modules[name]; present {
+		return nil, []error{
+			// seven characters at the start of the second line to align with the string "error: "
+			fmt.Errorf("module %q already defined\n"+
+				"       %s <-- previous definition here", name, group.modules[0].pos),
+		}
+	}
+
+	s.modules[name] = group
+
+	return nil, []error{}
+}
+
+func (s *SimpleNameInterface) ModuleFromName(moduleName string, namespace Namespace) (group ModuleGroup, found bool) {
+	group, found = s.modules[moduleName]
+	return group, found
+}
+
+func (s *SimpleNameInterface) Rename(oldName string, newName string, namespace Namespace) (errs []error) {
+	existingGroup, exists := s.modules[newName]
+	if exists {
+		errs = append(errs,
+			// seven characters at the start of the second line to align with the string "error: "
+			fmt.Errorf("renaming module %q to %q conflicts with existing module\n"+
+				"       %s <-- existing module defined here",
+				oldName, newName, existingGroup.modules[0].pos),
+		)
+		return errs
+	}
+
+	group := s.modules[oldName]
+	s.modules[newName] = group
+	delete(s.modules, group.name)
+	group.name = newName
+	return []error{}
+}
+
+func (s *SimpleNameInterface) AllModules() []ModuleGroup {
+	groups := make([]ModuleGroup, 0, len(s.modules))
+	for _, group := range s.modules {
+		groups = append(groups, group)
+	}
+
+	duplicateName := ""
+	less := func(i, j int) bool {
+		if groups[i].name == groups[j].name {
+			duplicateName = groups[i].name
+		}
+		return groups[i].name < groups[j].name
+	}
+	sort.Slice(groups, less)
+	if duplicateName != "" {
+		// It is permitted to have two moduleGroup's with the same name, but not within the same
+		// Namespace. The SimpleNameInterface should catch this in NewModule, however, so this
+		// should never happen.
+		panic(fmt.Sprintf("Duplicate moduleGroup name %q", duplicateName))
+	}
+	return groups
+}
+
+func (s *SimpleNameInterface) MissingDependencyError(depender string, dependerNamespace Namespace, dependency string) (err error) {
+	return fmt.Errorf("%q depends on undefined module %q", depender, dependency)
+}
+
+func (s *SimpleNameInterface) GetNamespace(ctx NamespaceContext) Namespace {
+	return nil
+}
diff --git a/visit_test.go b/visit_test.go
index d423c7a..3aa0f1b 100644
--- a/visit_test.go
+++ b/visit_test.go
@@ -141,7 +141,7 @@
 func TestVisit(t *testing.T) {
 	ctx := setupVisitTest(t)
 
-	topModule := ctx.modulesFromName("A")[0].logicModule.(*visitModule)
+	topModule := ctx.modulesFromName("A", nil)[0].logicModule.(*visitModule)
 	assertString(t, topModule.properties.VisitDepsDepthFirst, "EDCB")
 	assertString(t, topModule.properties.VisitDepsDepthFirstIf, "EDC")
 	assertString(t, topModule.properties.VisitDirectDeps, "B")