acceptMarksInPlace function
Accepts the inline change marks of yamlText (decoded against tree) in
place, only inside the section under when given (/-separated section
ids); see the file comment.
Throws MarksSectionNotFound when under names no section.
Implementation
MarksInPlaceResult acceptMarksInPlace(
String yamlText,
SomMetaTree tree, {
String? under,
}) {
final orig = _snapshot(SpecDocumentYaml.decode(yamlText, tree).document);
final expected = SpecDocumentYaml.decode(yamlText, tree).document;
final report = SpecReviewAnnotations(expected).acceptAllMarks();
final lines = yamlText.split('\n');
var from = 0, to = lines.length;
String? sectionLines;
if (under != null) {
for (final id in under.split('/')) {
final re = RegExp('^( *)${RegExp.escape(id)}( [A-Za-z0-9]+)?:');
var k = from;
while (k < to && re.firstMatch(lines[k]) == null) {
k++;
}
if (k >= to) throw MarksSectionNotFound(id, lines[from]);
final ind = re.firstMatch(lines[k])!.group(1)!.length;
var e = k + 1;
while (e < to &&
(lines[e].isEmpty ||
lines[e].length - lines[e].trimLeft().length > ind)) {
e++;
}
from = k;
to = e;
}
sectionLines = '${from + 1}-$to';
}
final out = <String>[];
var changed = 0;
var i = 0;
while (i < lines.length) {
final l = lines[i];
if (i < from || i >= to) {
out.add(l);
i++;
continue;
}
final q = RegExp(
r'^(\s*[A-Za-z][A-Za-z0-9]*: )"(\{~~[^"~]*~>([^"~]*)~~\})"\s*$',
).firstMatch(l);
if (q != null) {
out.add('${q.group(1)}"${q.group(3)}"');
changed++;
i++;
continue;
}
out.add(l);
i++;
if (!l.endsWith(': |2-')) continue;
final col =
l.length -
l.trimLeft().length +
(l.trimLeft().startsWith('- ') ? 2 : 0);
final ind = ' ' * (col + 2);
var j = i;
var lastBody = i - 1;
while (j < lines.length && (lines[j].isEmpty || lines[j].startsWith(ind))) {
if (lines[j].isNotEmpty) lastBody = j;
j++;
}
final body = lines.sublist(i, lastBody + 1);
final value = body
.map((s) => s.isEmpty ? '' : s.substring(ind.length))
.join('\n');
final nv = applyInlineMarksText(value, accept: true);
if (nv != value) {
changed++;
if (nv.isNotEmpty) {
out.addAll(nv.split('\n').map((s) => s.isEmpty ? '' : '$ind$s'));
}
} else {
out.addAll(body);
}
i = lastBody + 1;
}
final result = out.join('\n');
final got = SpecDocumentYaml.decode(result, tree).document;
final a = _snapshot(expected), b = _snapshot(got);
final differences = <String>[];
var count = 0;
String clip(String? v) =>
v == null ? 'null' : v.substring(0, v.length.clamp(0, 200));
for (final k in {...a.keys, ...b.keys}) {
String n(String? v) => v ?? '';
if (n(a[k]) != n(b[k]) && (under == null || n(orig[k]) != n(b[k]))) {
if (count++ < 10) {
differences.add(
'DIFF $k\n runtime: ${clip(a[k])}\n file: ${clip(b[k])}',
);
}
}
}
return MarksInPlaceResult(
text: result,
applied: report.applied.length,
malformed: report.malformed.length,
changedValues: changed,
differences: differences,
differenceCount: count,
marksLeft: SpecReviewAnnotations(got).counts().toJson(),
sectionLines: sectionLines,
);
}