Skip to content

Commit e659cb9

Browse files
committed
Skip comments and include \n in map mutations
1 parent e610993 commit e659cb9

File tree

1 file changed

+53
-12
lines changed

1 file changed

+53
-12
lines changed

lib/src/map_mutations.dart

+53-12
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ SourceEdit updateInMap(
3636
/// removing the element at [key] when re-parsed.
3737
SourceEdit removeInMap(YamlEditor yamlEdit, YamlMap map, Object? key) {
3838
assert(containsKey(map, key));
39-
final keyNode = getKeyNode(map, key);
39+
final (_, keyNode) = getKeyNode(map, key);
4040
final valueNode = map.nodes[keyNode]!;
4141

4242
if (map.style == CollectionStyle.FLOW) {
@@ -83,13 +83,14 @@ SourceEdit _addToBlockMap(
8383
}
8484
}
8585

86-
var valueString = yamlEncodeBlock(newValue, newIndentation, lineEnding);
86+
final valueString = yamlEncodeBlock(newValue, newIndentation, lineEnding);
87+
8788
if (isCollection(newValue) &&
8889
!isFlowYamlCollectionNode(newValue) &&
8990
!isEmpty(newValue)) {
90-
formattedValue += '$keyString:$lineEnding$valueString$lineEnding';
91+
formattedValue += '$keyString:$lineEnding$valueString';
9192
} else {
92-
formattedValue += '$keyString: $valueString$lineEnding';
93+
formattedValue += '$keyString: $valueString';
9394
}
9495

9596
return SourceEdit(offset, 0, formattedValue);
@@ -127,12 +128,18 @@ SourceEdit _replaceInBlockMap(
127128
YamlEditor yamlEdit, YamlMap map, Object? key, YamlNode newValue) {
128129
final yaml = yamlEdit.toString();
129130
final lineEnding = getLineEnding(yaml);
130-
final newIndentation =
131-
getMapIndentation(yaml, map) + getIndentation(yamlEdit);
131+
final mapIndentation = getMapIndentation(yaml, map);
132+
final newIndentation = mapIndentation + getIndentation(yamlEdit);
133+
134+
// TODO: Compensate for the indent eaten up
135+
final (keyIndex, keyNode) = getKeyNode(map, key);
136+
137+
var valueAsString = yamlEncodeBlock(
138+
wrapAsYamlNode(newValue),
139+
newIndentation,
140+
lineEnding,
141+
);
132142

133-
final keyNode = getKeyNode(map, key);
134-
var valueAsString =
135-
yamlEncodeBlock(wrapAsYamlNode(newValue), newIndentation, lineEnding);
136143
if (isCollection(newValue) &&
137144
!isFlowYamlCollectionNode(newValue) &&
138145
!isEmpty(newValue)) {
@@ -150,9 +157,43 @@ SourceEdit _replaceInBlockMap(
150157
var end = getContentSensitiveEnd(map.nodes[key]!);
151158

152159
/// `package:yaml` parses empty nodes in a way where the start/end of the
153-
/// empty value node is the end of the key node, so we have to adjust for
154-
/// this.
155-
if (end < start) end = start;
160+
/// empty value node is the end of the key node.
161+
///
162+
/// In our case, we need to ensure that any line-breaks are included in the
163+
/// edit such that:
164+
/// 1. We account for `\n` after a key within other keys or at the start
165+
/// Example..
166+
/// a:
167+
/// b: value
168+
///
169+
/// or..
170+
/// a: value
171+
/// b:
172+
/// c: value
173+
///
174+
/// 2. We don't suggest edits that are not within the string bounds because
175+
/// of the `\n` we need to account for in Rule 1 above. This could be a
176+
/// key:
177+
/// * At the index `0` but it's the only key
178+
/// * At the end in a map with more than one key
179+
end = start == yaml.length
180+
? start
181+
: end < start
182+
? start + 1
183+
: end;
184+
185+
// Aggressively skip all comments
186+
final (offsetOfLastComment, _) =
187+
skipAndExtractCommentsInBlock(yaml, end, null, lineEnding);
188+
end = offsetOfLastComment;
189+
190+
valueAsString =
191+
normalizeEncodedBlock(yaml, lineEnding, end, newValue, valueAsString);
192+
193+
/// [skipAndExtractCommentsInBlock] is greedy and eats up any whitespace
194+
/// it encounters in search of comments. Compensate indent lost in the
195+
/// current edit
196+
if (keyIndex != map.length - 1) valueAsString += ' ' * mapIndentation;
156197

157198
return SourceEdit(start, end - start, valueAsString);
158199
}

0 commit comments

Comments
 (0)