Files
libopenapi/index/map_index_nodes.go
quobix 7afb1e9d11 Addressed #159
Cleaned up all interesting static checks. All that is left is cosmetics.

Signed-off-by: quobix <dave@quobix.com>
2024-02-06 22:13:41 -05:00

93 lines
2.5 KiB
Go

// Copyright 2023 Princess B33f Heavy Industries / Dave Shanley
// SPDX-License-Identifier: MIT
package index
import (
"gopkg.in/yaml.v3"
)
type nodeMap struct {
line int
column int
node *yaml.Node
}
// NodeOrigin represents where a node has come from within a specification. This is not useful for single file specs,
// but becomes very, very important when dealing with exploded specifications, and we need to know where in the mass
// of files a node has come from.
type NodeOrigin struct {
// Node is the node in question
Node *yaml.Node `json:"-"`
// Line is yhe original line of where the node was found in the original file
Line int `json:"line" yaml:"line"`
// Column is the original column of where the node was found in the original file
Column int `json:"column" yaml:"column"`
// AbsoluteLocation is the absolute path to the reference was extracted from.
// This can either be an absolute path to a file, or a URL.
AbsoluteLocation string `json:"absolute_location" yaml:"absolute_location"`
// Index is the index that contains the node that was located in.
Index *SpecIndex `json:"-" yaml:"-"`
}
// GetNode returns a node from the spec based on a line and column. The second return var bool is true
// if the node was found, false if not.
func (index *SpecIndex) GetNode(line int, column int) (*yaml.Node, bool) {
if index.nodeMap[line] == nil {
return nil, false
}
node := index.nodeMap[line][column]
return node, node != nil
}
// MapNodes maps all nodes in the document to a map of line/column to node.
func (index *SpecIndex) MapNodes(rootNode *yaml.Node) {
cruising := make(chan bool)
nodeChan := make(chan *nodeMap)
go func(nodeChan chan *nodeMap) {
done := false
for !done {
node, ok := <-nodeChan
if !ok {
done = true
cruising <- true
return
}
if index.nodeMap[node.line] == nil {
index.nodeMap[node.line] = make(map[int]*yaml.Node)
}
index.nodeMap[node.line][node.column] = node.node
}
}(nodeChan)
go enjoyALuxuryCruise(rootNode, nodeChan, true)
<-cruising
close(cruising)
index.nodeMapCompleted <- true
close(index.nodeMapCompleted)
}
func enjoyALuxuryCruise(node *yaml.Node, nodeChan chan *nodeMap, root bool) {
if len(node.Content) > 0 {
for _, child := range node.Content {
nodeChan <- &nodeMap{
line: child.Line,
column: child.Column,
node: child,
}
enjoyALuxuryCruise(child, nodeChan, false)
}
}
nodeChan <- &nodeMap{
line: node.Line,
column: node.Column,
node: node,
}
if root {
close(nodeChan)
}
}