Schedule underlay groups as dependency forests
This commit is contained in:
@@ -89,6 +89,15 @@ func (graph importInclusionGraph) clone() importInclusionGraph {
|
||||
return cloned
|
||||
}
|
||||
|
||||
func mergeImportInclusionGraph(target *importInclusionGraph, source importInclusionGraph) {
|
||||
for _, node := range source.nodes {
|
||||
target.addNode(node)
|
||||
}
|
||||
for _, edge := range source.edges {
|
||||
target.addEdge(edge.importer, edge.imported, edge.location)
|
||||
}
|
||||
}
|
||||
|
||||
func (graph importInclusionGraph) scheduleCycle(closingEdge int, location Location) (Diagnostic, bool) {
|
||||
keys := make([]dependencyKey, len(graph.nodes))
|
||||
for index, node := range graph.nodes {
|
||||
@@ -149,21 +158,41 @@ func (graph importInclusionGraph) scheduleCycle(closingEdge int, location Locati
|
||||
}
|
||||
|
||||
func scheduleAcquisitionScope(scope acquisitionScope, graph importInclusionGraph) acquisitionScope {
|
||||
positions := make(map[importNodeKey]int, len(scope.contributions))
|
||||
slots := make([]int, 0, len(scope.contributions))
|
||||
keys := make([]dependencyKey, 0, len(scope.contributions))
|
||||
for index, contribution := range scope.contributions {
|
||||
if contribution.scopeOwner != scope.owner {
|
||||
continue
|
||||
}
|
||||
positions[contribution.identity] = len(keys)
|
||||
slots = append(slots, index)
|
||||
keys = append(keys, contribution.identity.dependencyKey())
|
||||
}
|
||||
if len(keys) < 2 {
|
||||
return scope
|
||||
}
|
||||
scheduled := scope
|
||||
scheduled.contributions = scheduleContributionSlots(scope.contributions, slots, graph)
|
||||
return scheduled
|
||||
}
|
||||
|
||||
func scheduleAcquisitionGroup(scopes []acquisitionScope, graph importInclusionGraph) acquisitionScope {
|
||||
var contributions []acquiredContribution
|
||||
for _, scope := range scopes {
|
||||
contributions = append(contributions, scope.contributions...)
|
||||
}
|
||||
slots := make([]int, len(contributions))
|
||||
for index := range slots {
|
||||
slots[index] = index
|
||||
}
|
||||
return acquisitionScope{contributions: scheduleContributionSlots(contributions, slots, graph)}
|
||||
}
|
||||
|
||||
func scheduleContributionSlots(contributions []acquiredContribution, slots []int, graph importInclusionGraph) []acquiredContribution {
|
||||
if len(slots) < 2 {
|
||||
return append([]acquiredContribution(nil), contributions...)
|
||||
}
|
||||
positions := make(map[importNodeKey]int, len(slots))
|
||||
keys := make([]dependencyKey, len(slots))
|
||||
for position, slot := range slots {
|
||||
contribution := contributions[slot]
|
||||
positions[contribution.identity] = position
|
||||
keys[position] = contribution.identity.dependencyKey()
|
||||
}
|
||||
edges := make([]dependencyEdge, 0, len(graph.edges))
|
||||
for _, edge := range graph.edges {
|
||||
importer, importerOK := positions[edge.importer]
|
||||
@@ -174,16 +203,86 @@ func scheduleAcquisitionScope(scope acquisitionScope, graph importInclusionGraph
|
||||
}
|
||||
order, _ := scheduleDependencies(keys, edges)
|
||||
if len(order) != len(keys) {
|
||||
return scope
|
||||
return append([]acquiredContribution(nil), contributions...)
|
||||
}
|
||||
scheduled := scope
|
||||
scheduled.contributions = append([]acquiredContribution(nil), scope.contributions...)
|
||||
scheduled := append([]acquiredContribution(nil), contributions...)
|
||||
for position, scheduledIndex := range order {
|
||||
scheduled.contributions[slots[position]] = scope.contributions[slots[scheduledIndex]]
|
||||
scheduled[slots[position]] = contributions[slots[scheduledIndex]]
|
||||
}
|
||||
return scheduled
|
||||
}
|
||||
|
||||
type importNamespaceAnchors struct {
|
||||
kind string
|
||||
host string
|
||||
native string
|
||||
input string
|
||||
}
|
||||
|
||||
func explicitNamespaceAnchor(group, input int) string {
|
||||
return fmt.Sprintf("%020d/%020d", group, input)
|
||||
}
|
||||
|
||||
func reanchorImportKey(key importNodeKey, anchors importNamespaceAnchors) importNodeKey {
|
||||
if anchors.kind != "" {
|
||||
key.namespaceKind = anchors.kind
|
||||
}
|
||||
switch {
|
||||
case key.resourceKind == "synthetic":
|
||||
key.namespaceAnchor = anchors.input
|
||||
case key.namespaceKind == "native":
|
||||
key.namespaceAnchor = anchors.native
|
||||
default:
|
||||
key.namespaceAnchor = anchors.host
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
func reanchorImportGraph(graph importInclusionGraph, anchors importNamespaceAnchors) (importInclusionGraph, map[importNodeKey]importNodeKey) {
|
||||
reanchored := newImportInclusionGraph()
|
||||
keys := make(map[importNodeKey]importNodeKey, len(graph.nodes))
|
||||
for _, node := range graph.nodes {
|
||||
old := node.key
|
||||
node.key = reanchorImportKey(old, anchors)
|
||||
keys[old] = node.key
|
||||
reanchored.addNode(node)
|
||||
}
|
||||
for _, edge := range graph.edges {
|
||||
reanchored.addEdge(keys[edge.importer], keys[edge.imported], edge.location)
|
||||
}
|
||||
return reanchored, keys
|
||||
}
|
||||
|
||||
func reanchorAcquisitionScope(scope *acquisitionScope, keys map[importNodeKey]importNodeKey, anchors importNamespaceAnchors) {
|
||||
if scope == nil {
|
||||
return
|
||||
}
|
||||
if key, exists := keys[scope.owner]; exists {
|
||||
scope.owner = key
|
||||
} else {
|
||||
scope.owner = reanchorImportKey(scope.owner, anchors)
|
||||
}
|
||||
for index := range scope.contributions {
|
||||
contribution := &scope.contributions[index]
|
||||
if key, exists := keys[contribution.identity]; exists {
|
||||
contribution.identity = key
|
||||
} else {
|
||||
contribution.identity = reanchorImportKey(contribution.identity, anchors)
|
||||
}
|
||||
if key, exists := keys[contribution.scopeOwner]; exists {
|
||||
contribution.scopeOwner = key
|
||||
} else {
|
||||
contribution.scopeOwner = reanchorImportKey(contribution.scopeOwner, anchors)
|
||||
}
|
||||
reanchorAcquisitionScope(contribution.pendingItem, keys, anchors)
|
||||
if contribution.nested != nil {
|
||||
for nestedIndex := range contribution.nested.acquisition {
|
||||
reanchorAcquisitionScope(&contribution.nested.acquisition[nestedIndex], keys, anchors)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func importKeyFor(access *filesystemAccess, canonical string, synthetic bool) importNodeKey {
|
||||
kind := "host"
|
||||
resourceKind := "file"
|
||||
|
||||
Reference in New Issue
Block a user