Skip to content

Commit dbaa6f5

Browse files
committed
Fix how CLI gets event data
1 parent df0367f commit dbaa6f5

3 files changed

Lines changed: 62 additions & 339 deletions

File tree

cmd/go-yaml/event.go

Lines changed: 9 additions & 286 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"bytes"
1010
"fmt"
1111
"io"
12-
"strings"
1312

1413
"go.yaml.in/yaml/v4"
1514
"go.yaml.in/yaml/v4/internal/libyaml"
@@ -68,59 +67,20 @@ func ProcessEvents(reader io.Reader, profuse, compact, unmarshal bool) error {
6867
return processEventsDecode(reader, profuse, compact)
6968
}
7069

71-
// processEventsDecode uses Loader.Load for YAML processing
70+
// processEventsDecode uses libyaml.Parser.Parse for YAML processing
7271
func processEventsDecode(reader io.Reader, profuse, compact bool) error {
7372
// Read all input from reader
7473
input, err := io.ReadAll(reader)
7574
if err != nil {
7675
return fmt.Errorf("failed to read input: %w", err)
7776
}
7877

79-
// Get implicit flags from libyaml parser
80-
implicitFlags, err := getDocumentImplicitFlags(input)
78+
// Get events from parser directly
79+
events, err := getEventsFromParser(input, profuse)
8180
if err != nil {
8281
return err
8382
}
8483

85-
// Use yaml.Loader to get events with comments
86-
loader, err := yaml.NewLoader(bytes.NewReader(input))
87-
if err != nil {
88-
return fmt.Errorf("failed to create loader: %w", err)
89-
}
90-
docIndex := 0
91-
var allEvents []*Event
92-
93-
for {
94-
var node yaml.Node
95-
err := loader.Load(&node)
96-
if err != nil {
97-
if err.Error() == "EOF" {
98-
break
99-
}
100-
return fmt.Errorf("failed to load YAML: %w", err)
101-
}
102-
103-
// Get events from node (includes comments)
104-
events := processNodeToEvents(&node, profuse)
105-
106-
// Augment document start/end events with implicit flags
107-
if docIndex < len(implicitFlags) {
108-
for _, event := range events {
109-
switch event.Type {
110-
case "DOCUMENT-START":
111-
event.Implicit = implicitFlags[docIndex].StartImplicit
112-
case "DOCUMENT-END":
113-
event.Implicit = implicitFlags[docIndex].EndImplicit
114-
}
115-
}
116-
}
117-
118-
allEvents = append(allEvents, events...)
119-
docIndex++
120-
}
121-
122-
events := allEvents
123-
12484
if compact {
12585
// For compact mode, output each event as a flow style mapping in a sequence
12686
for _, event := range events {
@@ -227,58 +187,20 @@ func processEventsDecode(reader io.Reader, profuse, compact bool) error {
227187
return nil
228188
}
229189

230-
// processEventsUnmarshal uses yaml.Unmarshal for YAML processing with implicit field augmentation
190+
// processEventsUnmarshal uses libyaml.Parser.Parse for YAML processing
231191
func processEventsUnmarshal(reader io.Reader, profuse, compact bool) error {
232192
// Read all input from reader
233193
input, err := io.ReadAll(reader)
234194
if err != nil {
235195
return fmt.Errorf("failed to read input: %w", err)
236196
}
237197

238-
// Get implicit flags from libyaml parser
239-
implicitFlags, err := getDocumentImplicitFlags(input)
198+
// Get events from parser directly
199+
events, err := getEventsFromParser(input, profuse)
240200
if err != nil {
241201
return err
242202
}
243203

244-
// Split input into documents
245-
documents := bytes.Split(input, []byte("---"))
246-
docIndex := 0
247-
var allEvents []*Event
248-
249-
for _, doc := range documents {
250-
// Skip empty documents
251-
if len(bytes.TrimSpace(doc)) == 0 {
252-
continue
253-
}
254-
255-
// Convert to yaml.Node for event processing
256-
var node yaml.Node
257-
if err := yaml.Load(doc, &node); err != nil {
258-
return fmt.Errorf("failed to load YAML to node: %w", err)
259-
}
260-
261-
// Get events from node (includes comments)
262-
events := processNodeToEvents(&node, profuse)
263-
264-
// Augment document start/end events with implicit flags
265-
if docIndex < len(implicitFlags) {
266-
for _, event := range events {
267-
switch event.Type {
268-
case "DOCUMENT-START":
269-
event.Implicit = implicitFlags[docIndex].StartImplicit
270-
case "DOCUMENT-END":
271-
event.Implicit = implicitFlags[docIndex].EndImplicit
272-
}
273-
}
274-
}
275-
276-
allEvents = append(allEvents, events...)
277-
docIndex++
278-
}
279-
280-
events := allEvents
281-
282204
if compact {
283205
// For compact mode, output each event as a flow style mapping in a sequence
284206
for _, event := range events {
@@ -385,166 +307,6 @@ func processEventsUnmarshal(reader io.Reader, profuse, compact bool) error {
385307
return nil
386308
}
387309

388-
// adjustColumn converts yaml.Node 1-based column to 0-based (libyaml format)
389-
func adjustColumn(col int) int {
390-
if col > 0 {
391-
return col - 1
392-
}
393-
return 0
394-
}
395-
396-
// processNodeToEvents converts a node to a slice of events for compact output
397-
func processNodeToEvents(node *yaml.Node, profuse bool) []*Event {
398-
var events []*Event
399-
400-
// Add document start event
401-
// yaml.Node uses 1-based columns, but we need 0-based (libyaml format)
402-
startCol := adjustColumn(node.Column)
403-
events = append(events, &Event{
404-
Type: "DOCUMENT-START",
405-
StartLine: node.Line,
406-
StartColumn: startCol,
407-
EndLine: node.Line,
408-
EndColumn: startCol,
409-
})
410-
411-
// Process the node content
412-
events = append(events, processNodeToEventsRecursive(node, profuse)...)
413-
414-
// Add document end event
415-
events = append(events, &Event{
416-
Type: "DOCUMENT-END",
417-
StartLine: node.Line,
418-
StartColumn: startCol,
419-
EndLine: node.Line,
420-
EndColumn: startCol,
421-
})
422-
423-
return events
424-
}
425-
426-
// processNodeToEventsRecursive recursively converts a node to events
427-
func processNodeToEventsRecursive(node *yaml.Node, profuse bool) []*Event {
428-
var events []*Event
429-
430-
switch node.Kind {
431-
case yaml.DocumentNode:
432-
for _, child := range node.Content {
433-
events = append(events, processNodeToEventsRecursive(child, profuse)...)
434-
}
435-
case yaml.MappingNode:
436-
startCol := adjustColumn(node.Column)
437-
events = append(events, &Event{
438-
Type: "MAPPING-START",
439-
StartLine: node.Line,
440-
StartColumn: startCol,
441-
EndLine: node.Line,
442-
EndColumn: startCol,
443-
Style: formatStyle(node.Style, profuse),
444-
HeadComment: node.HeadComment,
445-
LineComment: node.LineComment,
446-
FootComment: node.FootComment,
447-
})
448-
for i := 0; i < len(node.Content); i += 2 {
449-
if i+1 < len(node.Content) {
450-
// Key
451-
keyEvents := processNodeToEventsRecursive(node.Content[i], profuse)
452-
events = append(events, keyEvents...)
453-
// Value
454-
valueEvents := processNodeToEventsRecursive(node.Content[i+1], profuse)
455-
events = append(events, valueEvents...)
456-
}
457-
}
458-
events = append(events, &Event{
459-
Type: "MAPPING-END",
460-
StartLine: node.Line,
461-
StartColumn: startCol,
462-
EndLine: node.Line,
463-
EndColumn: startCol,
464-
})
465-
case yaml.SequenceNode:
466-
startCol := adjustColumn(node.Column)
467-
events = append(events, &Event{
468-
Type: "SEQUENCE-START",
469-
StartLine: node.Line,
470-
StartColumn: startCol,
471-
EndLine: node.Line,
472-
EndColumn: startCol,
473-
Style: formatStyle(node.Style, profuse),
474-
HeadComment: node.HeadComment,
475-
LineComment: node.LineComment,
476-
FootComment: node.FootComment,
477-
})
478-
for _, child := range node.Content {
479-
childEvents := processNodeToEventsRecursive(child, profuse)
480-
events = append(events, childEvents...)
481-
}
482-
events = append(events, &Event{
483-
Type: "SEQUENCE-END",
484-
StartLine: node.Line,
485-
StartColumn: startCol,
486-
EndLine: node.Line,
487-
EndColumn: startCol,
488-
})
489-
case yaml.ScalarNode:
490-
// Calculate end position for scalars based on value length
491-
// yaml.Node uses 1-based columns, adjust to 0-based
492-
startCol := adjustColumn(node.Column)
493-
endLine := node.Line
494-
endColumn := startCol
495-
if node.Value != "" {
496-
// For single-line values, add the length to the column
497-
if !strings.Contains(node.Value, "\n") {
498-
endColumn = startCol + len(node.Value)
499-
}
500-
}
501-
502-
// Filter out default YAML tags
503-
tag := node.Tag
504-
// Check if the tag was explicit in the input
505-
tagWasExplicit := node.Style&yaml.TaggedStyle != 0
506-
507-
// Show !!str only if it was explicit in the input
508-
if tag == "!!str" {
509-
if !tagWasExplicit {
510-
tag = ""
511-
}
512-
}
513-
// Show all other tags (no filtering)
514-
515-
events = append(events, &Event{
516-
Type: "SCALAR",
517-
Value: node.Value,
518-
Anchor: node.Anchor,
519-
Tag: tag,
520-
StartLine: node.Line,
521-
StartColumn: startCol,
522-
EndLine: endLine,
523-
EndColumn: endColumn,
524-
Style: formatStyle(node.Style, profuse),
525-
HeadComment: node.HeadComment,
526-
LineComment: node.LineComment,
527-
FootComment: node.FootComment,
528-
})
529-
case yaml.AliasNode:
530-
// Generate ALIAS event for alias nodes
531-
startCol := adjustColumn(node.Column)
532-
events = append(events, &Event{
533-
Type: "ALIAS",
534-
Value: node.Value,
535-
StartLine: node.Line,
536-
StartColumn: startCol,
537-
EndLine: node.Line,
538-
EndColumn: startCol,
539-
HeadComment: node.HeadComment,
540-
LineComment: node.LineComment,
541-
FootComment: node.FootComment,
542-
})
543-
}
544-
545-
return events
546-
}
547-
548310
// formatEventInfo converts an Event to an EventInfo struct for YAML encoding
549311
func formatEventInfo(event *Event, profuse bool) *EventInfo {
550312
info := &EventInfo{
@@ -605,48 +367,6 @@ func formatEventInfo(event *Event, profuse bool) *EventInfo {
605367
return info
606368
}
607369

608-
// DocumentImplicitFlags holds implicit flags for document start and end events
609-
type DocumentImplicitFlags struct {
610-
StartImplicit bool
611-
EndImplicit bool
612-
}
613-
614-
// getDocumentImplicitFlags extracts implicit flags for all documents
615-
func getDocumentImplicitFlags(input []byte) ([]*DocumentImplicitFlags, error) {
616-
p := libyaml.NewParser()
617-
if len(input) == 0 {
618-
input = []byte{'\n'}
619-
}
620-
p.SetInputString(input)
621-
622-
var flags []*DocumentImplicitFlags
623-
var currentDoc *DocumentImplicitFlags
624-
var ev libyaml.Event
625-
626-
for {
627-
if err := p.Parse(&ev); err != nil {
628-
return nil, fmt.Errorf("failed to parse YAML: %w", err)
629-
}
630-
631-
switch ev.Type {
632-
case libyaml.DOCUMENT_START_EVENT:
633-
currentDoc = &DocumentImplicitFlags{
634-
StartImplicit: ev.Implicit,
635-
}
636-
flags = append(flags, currentDoc)
637-
case libyaml.DOCUMENT_END_EVENT:
638-
if currentDoc != nil {
639-
currentDoc.EndImplicit = ev.Implicit
640-
}
641-
case libyaml.STREAM_END_EVENT:
642-
ev.Delete()
643-
return flags, nil
644-
}
645-
646-
ev.Delete()
647-
}
648-
}
649-
650370
// getEventsFromParser parses YAML input and extracts events with implicit field information
651371
func getEventsFromParser(input []byte, profuse bool) ([]*Event, error) {
652372
p := libyaml.NewParser()
@@ -690,6 +410,9 @@ func convertLibyamlEvent(ev *libyaml.Event, profuse bool) *Event {
690410
StartColumn: ev.StartMark.Column,
691411
EndLine: ev.EndMark.Line + 1,
692412
EndColumn: ev.EndMark.Column,
413+
HeadComment: string(ev.HeadComment),
414+
LineComment: string(ev.LineComment),
415+
FootComment: string(ev.FootComment),
693416
}
694417

695418
switch ev.Type {

cmd/go-yaml/testdata/comments.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@
5151
event: |
5252
- {event: DOCUMENT-START}
5353
- {event: MAPPING-START}
54-
- {event: SCALAR, value: key, head: '# head comment', foot: '# foot comment'}
55-
- {event: SCALAR, value: value, line: '# line comment'}
54+
- {event: SCALAR, value: key, head: '# head comment'}
55+
- {event: SCALAR, value: value, line: '# line comment', foot: '# foot comment'}
5656
- {event: MAPPING-END}
5757
- {event: DOCUMENT-END}
5858

0 commit comments

Comments
 (0)