Centralize parser diagnostic translation

This commit is contained in:
2026-09-07 01:04:08 +00:00
parent 49e04442da
commit a04d32c389
5 changed files with 26 additions and 38 deletions

View File

@@ -10,6 +10,7 @@ module and package documentation boundary. Its implemented public primitives are
- a parser-independent ordered tree in `internal/document`;
- the sole upstream YAML integration in `internal/yaml`, which translates validated
input into that owned tree and exposes no parser types outside its boundary;
`parse.go` owns shared translation into detached, ordered public diagnostics;
- a private strict composer in `compose.go` that joins only disjoint document-tree
definitions, retains ordered claims and composite mapping origins, reports every
conflicting location, and never aliases an input tree;

View File

@@ -92,7 +92,13 @@ is not required to justify removing provably unread clones.
## Stage 2 — Centralize parser issue translation
Status: pending.
Status: complete.
Completion: `parserDiagnostics` in `parse.go` now owns detached, canonical
translation for selected, imported, and profile sources. Existing tests cover
safe selected-source errors and imported/profile source attribution, so no
duplicate regression was added. Full offline tests, vet, build, and whitespace
checks passed with Go 1.26.7 on Linux/amd64.
Evidence: [parse.go](../../parse.go) translates adapter issues inline, while
`importParseDiagnostics` in [imports.go](../../imports.go) repeats the translation

View File

@@ -345,7 +345,7 @@ func (s *importTraversal) visitPath(basePath string, declaration importDeclarati
Depth: maxDocumentDepth, Nodes: maxDocumentNodes,
})
if len(issues) != 0 {
return importParseDiagnostics(sourceID, issues)
return parserDiagnostics(sourceID, issues)
}
nodeCount := countInputNodes(root)
if s.usedNodes+nodeCount > s.limits.nodes {
@@ -625,20 +625,6 @@ func sourceInfos(source *SourceInfo) []SourceInfo {
return []SourceInfo{cloneSourceInfo(*source)}
}
func importParseDiagnostics(sourceID string, issues []yamladapter.Issue) []Diagnostic {
diagnostics := make([]Diagnostic, len(issues))
for index, issue := range issues {
diagnostics[index] = Diagnostic{
Code: Code(issue.Code), Severity: SeverityError, Message: issue.Message,
Primary: &Location{SourceID: sourceID, Line: issue.Line, Column: issue.Column},
}
for _, related := range issue.Related {
diagnostics[index].Related = append(diagnostics[index].Related, publicLocation(related))
}
}
return diagnostics
}
func importDiagnostic(code Code, message string, location *Location) Diagnostic {
return Diagnostic{Code: code, Severity: SeverityError, Message: message, Primary: cloneLocation(location)}
}

View File

@@ -33,6 +33,21 @@ type parsedSource struct {
bytes int64
}
// parserDiagnostics translates adapter issues into detached, ordered public records.
func parserDiagnostics(sourceID string, issues []yamladapter.Issue) []Diagnostic {
diagnostics := make([]Diagnostic, len(issues))
for index, issue := range issues {
diagnostics[index] = Diagnostic{
Code: Code(issue.Code), Severity: SeverityError, Message: issue.Message,
Primary: &Location{SourceID: sourceID, Line: issue.Line, Column: issue.Column},
}
for _, related := range issue.Related {
diagnostics[index].Related = append(diagnostics[index].Related, publicLocation(related))
}
}
return canonicalDiagnostics(diagnostics)
}
func parseSource(source Source, sourceID string, limits parseLimits) (parsedSource, []Diagnostic) {
read, diagnostics := readSource(source, sourceID, limits.source)
if len(diagnostics) != 0 || read.info == nil {
@@ -41,27 +56,7 @@ func parseSource(source Source, sourceID string, limits parseLimits) (parsedSour
root, issues := yamladapter.Parse(bytes.NewReader(read.data), sourceID, limits.document)
if len(issues) != 0 {
diagnostics := make([]Diagnostic, len(issues))
for i, issue := range issues {
diagnostics[i] = Diagnostic{
Code: Code(issue.Code),
Severity: SeverityError,
Message: issue.Message,
Primary: &Location{
SourceID: sourceID,
Line: issue.Line,
Column: issue.Column,
},
}
for _, related := range issue.Related {
diagnostics[i].Related = append(diagnostics[i].Related, Location{
SourceID: related.SourceID,
Line: related.Line,
Column: related.Column,
})
}
}
return parsedSource{source: read.info, bytes: int64(len(read.data))}, canonicalDiagnostics(diagnostics)
return parsedSource{source: read.info, bytes: int64(len(read.data))}, parserDiagnostics(sourceID, issues)
}
return parsedSource{document: root, source: read.info, bytes: int64(len(read.data))}, nil
}

View File

@@ -86,7 +86,7 @@ func loadProfileDocument(source Source, context *FilesystemContext, main parsedS
profileRoot, issues := yamladapter.Parse(bytes.NewReader(data), sourceID, yamladapter.Limits{Depth: maxDocumentDepth, Nodes: maxDocumentNodes})
if len(issues) != 0 {
_ = root.Close()
return nil, sources, importParseDiagnostics(sourceID, issues)
return nil, sources, parserDiagnostics(sourceID, issues)
}
nodeCount := countInputNodes(profileRoot)
if base.inputNodes+nodeCount > limits.nodes {