184 lines
4.5 KiB
Go
184 lines
4.5 KiB
Go
package gsp
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
var resolutionRank = map[string]int{
|
|
"": 0,
|
|
"L0": 0,
|
|
"L1": 1,
|
|
"L2": 2,
|
|
"L3": 3,
|
|
"L4": 4,
|
|
"L5": 5,
|
|
}
|
|
|
|
type Unit struct {
|
|
ID string `json:"id" yaml:"id"`
|
|
Title string `json:"title,omitempty" yaml:"title"`
|
|
Context string `json:"context,omitempty" yaml:"context"`
|
|
Resolution string `json:"resolution,omitempty" yaml:"resolution"`
|
|
With Relations `json:"with,omitempty" yaml:"with"`
|
|
Refines string `json:"refines,omitempty" yaml:"refines"`
|
|
Type string `json:"type,omitempty" yaml:"type"`
|
|
File string `json:"file,omitempty" yaml:"-"`
|
|
}
|
|
|
|
type Relation struct {
|
|
ID string `json:"id" yaml:"id"`
|
|
Context string `json:"context,omitempty" yaml:"context"`
|
|
}
|
|
|
|
type Relations []Relation
|
|
|
|
func (r *Relations) UnmarshalYAML(value *yaml.Node) error {
|
|
if value.Kind == 0 || value.Tag == "!!null" {
|
|
*r = nil
|
|
return nil
|
|
}
|
|
if value.Kind != yaml.SequenceNode {
|
|
return fmt.Errorf("with must be a list")
|
|
}
|
|
out := make([]Relation, 0, len(value.Content))
|
|
for _, item := range value.Content {
|
|
switch item.Kind {
|
|
case yaml.ScalarNode:
|
|
if item.Value == "" {
|
|
return fmt.Errorf("with item cannot be empty")
|
|
}
|
|
out = append(out, Relation{ID: item.Value})
|
|
case yaml.MappingNode:
|
|
var rel Relation
|
|
if err := item.Decode(&rel); err != nil {
|
|
return err
|
|
}
|
|
if rel.ID == "" {
|
|
return fmt.Errorf("with object item requires id")
|
|
}
|
|
out = append(out, rel)
|
|
default:
|
|
return fmt.Errorf("with item must be a string or object")
|
|
}
|
|
}
|
|
*r = out
|
|
return nil
|
|
}
|
|
|
|
type Issue struct {
|
|
Level string `json:"level"`
|
|
Code string `json:"code"`
|
|
ID string `json:"id,omitempty"`
|
|
File string `json:"file,omitempty"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
type Report struct {
|
|
OK bool `json:"ok"`
|
|
Errors []Issue `json:"errors,omitempty"`
|
|
Warnings []Issue `json:"warnings,omitempty"`
|
|
Notices []Issue `json:"notices,omitempty"`
|
|
}
|
|
|
|
func (r *Report) addError(code, id, file, message string) {
|
|
r.Errors = append(r.Errors, Issue{Level: "error", Code: code, ID: id, File: file, Message: message})
|
|
r.OK = false
|
|
}
|
|
|
|
func (r *Report) addWarning(code, id, file, message string) {
|
|
r.Warnings = append(r.Warnings, Issue{Level: "warning", Code: code, ID: id, File: file, Message: message})
|
|
}
|
|
|
|
func (r *Report) addNotice(code, id, file, message string) {
|
|
r.Notices = append(r.Notices, Issue{Level: "notice", Code: code, ID: id, File: file, Message: message})
|
|
}
|
|
|
|
type Project struct {
|
|
Root string
|
|
Manifest *Manifest
|
|
Units []*Unit
|
|
ByID map[string]*Unit
|
|
Duplicates map[string][]*Unit
|
|
LoadIssues []Issue
|
|
}
|
|
|
|
type IndexEntry struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title,omitempty"`
|
|
File string `json:"file"`
|
|
Type string `json:"type,omitempty"`
|
|
Resolution string `json:"resolution,omitempty"`
|
|
With []string `json:"with,omitempty"`
|
|
Refines string `json:"refines,omitempty"`
|
|
}
|
|
|
|
type FlattenResult struct {
|
|
Entry string `json:"entry"`
|
|
Depth int `json:"depth"`
|
|
Units []*Unit `json:"units"`
|
|
Warnings []Issue `json:"warnings,omitempty"`
|
|
}
|
|
|
|
type TraceResult struct {
|
|
Entry string `json:"entry"`
|
|
Depth int `json:"depth"`
|
|
Nodes []*Unit `json:"nodes"`
|
|
Edges []GraphEdge `json:"edges"`
|
|
Warnings []Issue `json:"warnings,omitempty"`
|
|
}
|
|
|
|
type PackResult struct {
|
|
Entry string `json:"entry"`
|
|
Depth int `json:"depth"`
|
|
Budget int `json:"budget,omitempty"`
|
|
Truncated bool `json:"truncated"`
|
|
Units []*Unit `json:"units"`
|
|
ApproxChars int `json:"approxChars"`
|
|
Warnings []Issue `json:"warnings,omitempty"`
|
|
}
|
|
|
|
type Graph struct {
|
|
Nodes []GraphNode `json:"nodes"`
|
|
Edges []GraphEdge `json:"edges"`
|
|
}
|
|
|
|
type GraphNode struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title,omitempty"`
|
|
Type string `json:"type,omitempty"`
|
|
Resolution string `json:"resolution,omitempty"`
|
|
File string `json:"file,omitempty"`
|
|
Missing bool `json:"missing,omitempty"`
|
|
}
|
|
|
|
type GraphEdge struct {
|
|
From string `json:"from"`
|
|
To string `json:"to"`
|
|
Kind string `json:"kind"`
|
|
}
|
|
|
|
type Filter struct {
|
|
IncludeTypes map[string]bool
|
|
ExcludeTypes map[string]bool
|
|
}
|
|
|
|
func (f Filter) Allows(unit *Unit) bool {
|
|
if unit == nil {
|
|
return false
|
|
}
|
|
if len(f.IncludeTypes) > 0 && !f.IncludeTypes[unit.Type] {
|
|
return false
|
|
}
|
|
if len(f.ExcludeTypes) > 0 && f.ExcludeTypes[unit.Type] {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func resolutionValue(value string) (int, bool) {
|
|
rank, ok := resolutionRank[value]
|
|
return rank, ok
|
|
}
|