Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/blueprint/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 8 kB image not shown  

Quelle  name_interface.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// 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"
 "strings"
 "unicode"
)

// 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)

 // Gets called when a module was pruned from the build tree by SourceRootDirs
 NewSkippedModule(ctx NamespaceContext, name string, skipInfo SkippedModuleInfo)

 // Finds the module with the given name
 ModuleFromName(moduleName string, namespace Namespace) (group ModuleGroup, found bool)

 // Finds if the module with the given name was skipped
 SkippedModuleFromName(moduleName string, namespace Namespace) (skipInfos []SkippedModuleInfo, skipped 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, guess []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)

 // returns a deterministic, unique, arbitrary string for the given name in the given namespace
 UniqueName(ctx NamespaceContext, name string) (unique string)
}

// A NamespaceContext stores the information given to a NameInterface to enable the NameInterface
// to choose the namespace for any given module
type NamespaceContext interface {
 ModulePath() string
}

type namespaceContextImpl struct {
 modulePath string
}

func newNamespaceContext(moduleInfo *moduleInfo) (ctx NamespaceContext) {
 return &namespaceContextImpl{moduleInfo.pos.Filename}
}

func newNamespaceContextFromFilename(filename string) NamespaceContext {
 return &namespaceContextImpl{filename}
}

func (ctx *namespaceContextImpl) ModulePath() string {
 return ctx.modulePath
}

type SkippedModuleInfo struct {
 filename string
 reason   string
}

// a SimpleNameInterface just stores all modules in a map based on name
type SimpleNameInterface struct {
 modules        map[string]ModuleGroup
 skippedModules map[string][]SkippedModuleInfo
}

func NewSimpleNameInterface() *SimpleNameInterface {
 return &SimpleNameInterface{
  modules:        make(map[string]ModuleGroup),
  skippedModules: make(map[string][]SkippedModuleInfo),
 }
}

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.firstModule().pos),
  }
 }

 if !IsValidModuleName(name) {
  return nil, []error{
   // seven characters at the start of the second line to align with the string "error: "
   fmt.Errorf("module %q should use a valid name.\n"+
    "       Special chars like spaces are not allowed.", name),
  }
 }

 s.modules[name] = group

 return nil, []error{}
}

// Leters, Digits, Underscore, `+` (libc++), `.` are valid chars for module names.
// Additional chars like `-` were added to the list to account for module names
// that predate the enforcement of this check.
var allowedSpecialCharsInModuleNames = map[rune]bool{
 '_': true,
 '-': true,
 '.': true,
 '/': true,
 '@': true,
 '+': true,
 '&': true,
}

func IsValidModuleName(name string) bool {
 for _, c := range name {
  _, allowedSpecialChar := allowedSpecialCharsInModuleNames[c]
  valid := unicode.IsLetter(c) || unicode.IsDigit(c) || allowedSpecialChar
  if !valid {
   return false
  }
 }
 return len(name) > 0
}

func (s *SimpleNameInterface) NewSkippedModule(ctx NamespaceContext, name string, info SkippedModuleInfo) {
 if name == "" {
  return
 }
 s.skippedModules[name] = append(s.skippedModules[name], info)
}

func (s *SimpleNameInterface) ModuleFromName(moduleName string, namespace Namespace) (group ModuleGroup, found bool) {
 group, found = s.modules[moduleName]
 return group, found
}

func (s *SimpleNameInterface) SkippedModuleFromName(moduleName string, namespace Namespace) (skipInfos []SkippedModuleInfo, skipped bool) {
 skipInfos, skipped = s.skippedModules[moduleName]
 return
}

func (s *SimpleNameInterface) Rename(oldName string, newName string, namespace Namespace) (errs []error) {
 existingGroup, exists := s.modules[newName]
 if exists {
  return []error{
   // 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.firstModule().pos),
  }
 }

 group, exists := s.modules[oldName]
 if !exists {
  return []error{fmt.Errorf("module %q to renamed to %q doesn't exist", oldName, newName)}
 }
 s.modules[newName] = group
 delete(s.modules, group.name)
 group.name = newName
 return nil
}

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, guess []string) (err error) {
 skipInfos, skipped := s.SkippedModuleFromName(dependency, dependerNamespace)
 if skipped {
  filesFound := make([]string, 0, len(skipInfos))
  reasons := make([]string, 0, len(skipInfos))
  for _, info := range skipInfos {
   filesFound = append(filesFound, info.filename)
   reasons = append(reasons, info.reason)
  }
  return fmt.Errorf(
   "module %q depends on skipped module %q; %q was defined in files(s) [%v], but was skipped for reason(s) [%v]",
   depender,
   dependency,
   dependency,
   strings.Join(filesFound, ", "),
   strings.Join(reasons, "; "),
  )
 }

 guessString := ""
 if len(guess) > 0 {
  guessString = fmt.Sprintf(" Did you mean %q?", guess)
 }
 return fmt.Errorf("%q depends on undefined module %q.%s", depender, dependency, guessString)
}

func (s *SimpleNameInterface) GetNamespace(ctx NamespaceContext) Namespace {
 return nil
}

func (s *SimpleNameInterface) UniqueName(ctx NamespaceContext, name string) (unique string) {
 return name
}

[Dauer der Verarbeitung: 0.21 Sekunden, vorverarbeitet 2026-06-28]