From 8c1cb6a5f0d198b528db4b514392f4ed38446b49 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Apr 2026 02:41:10 +0000 Subject: [PATCH] Refactor EncodeSeparate+TomlInline into a single EncodeHint enum Agent-Logs-Url: https://github.com/mikefarah/yq/sessions/24db9a8f-601d-4ccf-ada7-129ed3226bb6 Co-authored-by: mikefarah <1151925+mikefarah@users.noreply.github.com> --- pkg/yqlib/candidate_node.go | 34 ++++++++++++++++++++++------------ pkg/yqlib/decoder_hcl.go | 2 +- pkg/yqlib/decoder_toml.go | 16 ++++++++-------- pkg/yqlib/encoder_hcl.go | 8 ++++---- pkg/yqlib/encoder_toml.go | 24 +++++++----------------- 5 files changed, 42 insertions(+), 42 deletions(-) diff --git a/pkg/yqlib/candidate_node.go b/pkg/yqlib/candidate_node.go index 0518eaad..92f14cde 100644 --- a/pkg/yqlib/candidate_node.go +++ b/pkg/yqlib/candidate_node.go @@ -27,6 +27,22 @@ const ( FlowStyle ) +// EncodeHint controls how a mapping node is serialised by format-specific encoders +// that distinguish between inline and block/section representations (e.g. TOML, HCL). +type EncodeHint int + +const ( + // EncodeHintDefault lets the encoder choose the representation (e.g. TOML block + // mappings default to [section] headers). + EncodeHintDefault EncodeHint = iota + // EncodeHintSeparateBlock forces the node to be emitted as a separate block or + // table-section header (used by TOML [section] and HCL block decoders). + EncodeHintSeparateBlock + // EncodeHintInline forces the node to be emitted as an inline / flow table + // (used by TOML inline-table decoder and TOML encoder). + EncodeHintInline +) + func createStringScalarNode(stringValue string) *CandidateNode { var node = &CandidateNode{Kind: ScalarNode} node.Value = stringValue @@ -97,12 +113,9 @@ type CandidateNode struct { // (e.g. top level cross document merge). This property does not propagate to child nodes. EvaluateTogether bool IsMapKey bool - // For formats like HCL and TOML: indicates that child entries should be emitted as separate blocks/tables - // rather than consolidated into nested mappings (default behaviour) - EncodeSeparate bool - // For TOML: indicates that this mapping was originally a TOML inline table and should be - // re-encoded as an inline table rather than a separate table section. - TomlInline bool + // EncodeHint controls how a mapping node is serialised by format-specific encoders + // (e.g. TOML, HCL) that support both inline and block/section representations. + EncodeHint EncodeHint } func (n *CandidateNode) CreateChild() *CandidateNode { @@ -414,8 +427,7 @@ func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode { EvaluateTogether: n.EvaluateTogether, IsMapKey: n.IsMapKey, - EncodeSeparate: n.EncodeSeparate, - TomlInline: n.TomlInline, + EncodeHint: n.EncodeHint, } if cloneContent { @@ -469,10 +481,8 @@ func (n *CandidateNode) UpdateAttributesFrom(other *CandidateNode, prefs assignP n.Anchor = other.Anchor } - // Preserve EncodeSeparate flag for format-specific encoding hints - n.EncodeSeparate = other.EncodeSeparate - // Preserve TomlInline flag for TOML inline table round-trips - n.TomlInline = other.TomlInline + // Preserve EncodeHint for format-specific encoding hints + n.EncodeHint = other.EncodeHint // merge will pickup the style of the new thing // when autocreating nodes diff --git a/pkg/yqlib/decoder_hcl.go b/pkg/yqlib/decoder_hcl.go index 731f9ff3..11cd0030 100644 --- a/pkg/yqlib/decoder_hcl.go +++ b/pkg/yqlib/decoder_hcl.go @@ -226,7 +226,7 @@ func addBlockToMapping(parent *CandidateNode, block *hclsyntax.Block, src []byte // Mark the type node if there are multiple blocks of this type at this level // This tells the encoder to emit them as separate blocks rather than consolidating them if isMultipleBlocksOfType { - typeNode.EncodeSeparate = true + typeNode.EncodeHint = EncodeHintSeparateBlock } } current = typeNode diff --git a/pkg/yqlib/decoder_toml.go b/pkg/yqlib/decoder_toml.go index dc4de390..a3e3a831 100644 --- a/pkg/yqlib/decoder_toml.go +++ b/pkg/yqlib/decoder_toml.go @@ -152,7 +152,7 @@ func (dec *tomlDecoder) createInlineTableMap(tomlNode *toml.Node) (*CandidateNod return &CandidateNode{ Kind: MappingNode, Tag: "!!map", - TomlInline: true, + EncodeHint: EncodeHintInline, Content: content, }, nil } @@ -346,10 +346,10 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) { } tableNodeValue := &CandidateNode{ - Kind: MappingNode, - Tag: "!!map", - Content: make([]*CandidateNode, 0), - EncodeSeparate: true, + Kind: MappingNode, + Tag: "!!map", + Content: make([]*CandidateNode, 0), + EncodeHint: EncodeHintSeparateBlock, } // Attach pending head comments to the table @@ -443,9 +443,9 @@ func (dec *tomlDecoder) processArrayTable(currentNode *toml.Node) (bool, error) hasValue := dec.parser.NextExpression() tableNodeValue := &CandidateNode{ - Kind: MappingNode, - Tag: "!!map", - EncodeSeparate: true, + Kind: MappingNode, + Tag: "!!map", + EncodeHint: EncodeHintSeparateBlock, } // Attach pending head comments to the array table diff --git a/pkg/yqlib/encoder_hcl.go b/pkg/yqlib/encoder_hcl.go index 8dce06ea..f592b81d 100644 --- a/pkg/yqlib/encoder_hcl.go +++ b/pkg/yqlib/encoder_hcl.go @@ -449,8 +449,8 @@ func (he *hclEncoder) encodeBlockIfMapping(body *hclwrite.Body, key string, valu return false } - // If EncodeSeparate is set, emit children as separate blocks regardless of label extraction - if valueNode.EncodeSeparate { + // If EncodeHintSeparateBlock is set, emit children as separate blocks regardless of label extraction + if valueNode.EncodeHint == EncodeHintSeparateBlock { if handled, _ := he.encodeMappingChildrenAsBlocks(body, key, valueNode); handled { return true } @@ -537,9 +537,9 @@ func (he *hclEncoder) encodeMappingChildrenAsBlocks(body *hclwrite.Body, blockTy return false, nil } - // Only emit as separate blocks if EncodeSeparate is true + // Only emit as separate blocks if EncodeHintSeparateBlock is set // This allows the encoder to respect the original block structure preserved by the decoder - if !valueNode.EncodeSeparate { + if valueNode.EncodeHint != EncodeHintSeparateBlock { return false, nil } diff --git a/pkg/yqlib/encoder_toml.go b/pkg/yqlib/encoder_toml.go index afcfd777..f91d1717 100644 --- a/pkg/yqlib/encoder_toml.go +++ b/pkg/yqlib/encoder_toml.go @@ -164,7 +164,7 @@ func (te *tomlEncoder) encodeTopLevelEntry(w io.Writer, path []string, node *Can case MappingNode: // Use inline table syntax for nodes explicitly marked as TOML inline tables // or YAML flow mappings. All other mappings become readable TOML table sections. - if node.TomlInline || node.Style&FlowStyle != 0 { + if node.EncodeHint == EncodeHintInline || node.Style&FlowStyle != 0 { return te.writeInlineTableAttribute(w, path[len(path)-1], node) } return te.encodeSeparateMapping(w, path, node) @@ -427,7 +427,7 @@ func (te *tomlEncoder) writeTableHeader(w io.Writer, path []string, m *Candidate // It emits the table header for this mapping if it has any content, then processes children. func (te *tomlEncoder) encodeSeparateMapping(w io.Writer, path []string, m *CandidateNode) error { // Check if this mapping has any non-mapping, non-array-of-tables children (i.e., attributes). - // TomlInline mapping children also count as attributes since they render as key = { ... }. + // Inline mapping children also count as attributes since they render as key = { ... }. hasAttrs := false for i := 0; i < len(m.Content); i += 2 { v := m.Content[i+1] @@ -435,7 +435,7 @@ func (te *tomlEncoder) encodeSeparateMapping(w io.Writer, path []string, m *Cand hasAttrs = true break } - if v.Kind == MappingNode && (v.TomlInline || v.Style&FlowStyle != 0) { + if v.Kind == MappingNode && (v.EncodeHint == EncodeHintInline || v.Style&FlowStyle != 0) { hasAttrs = true break } @@ -511,21 +511,11 @@ func (te *tomlEncoder) encodeSeparateMapping(w io.Writer, path []string, m *Cand return nil } -func (te *tomlEncoder) hasEncodeSeparateChild(m *CandidateNode) bool { - for i := 0; i < len(m.Content); i += 2 { - v := m.Content[i+1] - if v.Kind == MappingNode && v.EncodeSeparate { - return true - } - } - return false -} - func (te *tomlEncoder) hasStructuralChildren(m *CandidateNode) bool { for i := 0; i < len(m.Content); i += 2 { v := m.Content[i+1] - // Only consider it structural if mapping has EncodeSeparate or is non-empty - if v.Kind == MappingNode && v.EncodeSeparate { + // Only consider it structural if mapping has EncodeHintSeparateBlock or is non-empty + if v.Kind == MappingNode && v.EncodeHint == EncodeHintSeparateBlock { return true } if v.Kind == SequenceNode { @@ -597,13 +587,13 @@ func (te *tomlEncoder) encodeMappingBodyWithPath(w io.Writer, path []string, m * } } - // Finally, child mappings: TomlInline or flow-style ones become inline table attributes, + // Finally, child mappings: inline-hint or flow-style ones become inline table attributes, // while all others are emitted as separate sub-table sections. for i := 0; i < len(m.Content); i += 2 { k := m.Content[i].Value v := m.Content[i+1] if v.Kind == MappingNode { - if v.TomlInline || v.Style&FlowStyle != 0 { + if v.EncodeHint == EncodeHintInline || v.Style&FlowStyle != 0 { if err := te.writeInlineTableAttribute(w, k, v); err != nil { return err }