Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,13 @@ func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node {
if !p.textless {
n.Line = p.event.start_mark.line + 1
n.Column = p.event.start_mark.column + 1
// end_mark is the position just past this event. For scalars and aliases
// it already spans the whole node. For mappings and sequences this is the
// MAPPING-START/SEQUENCE-START event, so it only marks the start for now;
// mapping()/sequence() overwrite it from the matching END event so the
// span covers the whole block.
n.EndLine = p.event.end_mark.line + 1
n.EndColumn = p.event.end_mark.column + 1
n.HeadComment = string(p.event.head_comment)
n.LineComment = string(p.event.line_comment)
n.FootComment = string(p.event.foot_comment)
Expand Down Expand Up @@ -264,6 +271,26 @@ func (p *parser) sequence() *Node {
}
n.LineComment = string(p.event.line_comment)
n.FootComment = string(p.event.foot_comment)
// End at the last item's end so the span reaches the end of the actual
// content, consistent with scalars/aliases. The SEQUENCE-END token sits at
// the start of the following line after a block dedent, which would
// overshoot the element. Empty sequences fall back to that token's mark.
if !p.textless {
if n.Style&FlowStyle != 0 {
// Flow collections close with an explicit `}`/`]`; the END token's
// mark is just past that delimiter, so the span covers the whole
// collection (and stays consistent with the empty-flow fallback,
// which has no last child and uses the same mark).
n.EndLine = p.event.end_mark.line + 1
n.EndColumn = p.event.end_mark.column + 1
} else if len(n.Content) > 0 {
last := n.Content[len(n.Content)-1]
n.EndLine, n.EndColumn = last.EndLine, last.EndColumn
} else {
n.EndLine = p.event.end_mark.line + 1
n.EndColumn = p.event.end_mark.column + 1
}
}
p.expect(yaml_SEQUENCE_END_EVENT)
return n
}
Expand Down Expand Up @@ -304,6 +331,28 @@ func (p *parser) mapping() *Node {
n.Content[len(n.Content)-2].FootComment = n.FootComment
n.FootComment = ""
}
// End at the last entry's value end so the span reaches the end of the
// actual content, consistent with scalars/aliases. The MAPPING-END token
// sits at the start of the following line after a block dedent, which would
// overshoot the element. Empty mappings fall back to that token's mark.
// (Origin __origin__ nodes are appended later, during decode, so the last
// element here is a real value.)
if !p.textless {
if n.Style&FlowStyle != 0 {
// Flow collections close with an explicit `}`/`]`; the END token's
// mark is just past that delimiter, so the span covers the whole
// collection (and stays consistent with the empty-flow fallback,
// which has no last child and uses the same mark).
n.EndLine = p.event.end_mark.line + 1
n.EndColumn = p.event.end_mark.column + 1
} else if len(n.Content) > 0 {
last := n.Content[len(n.Content)-1]
n.EndLine, n.EndColumn = last.EndLine, last.EndColumn
} else {
n.EndLine = p.event.end_mark.line + 1
n.EndColumn = p.event.end_mark.column + 1
}
}
p.expect(yaml_MAPPING_END_EVENT)
return n
}
Expand Down
Loading
Loading