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
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ export interface IDocumentDiff {
};
/** Optional authoritative zero-based source row correspondence. Null denotes padding. */
readonly contextGaps?: readonly IDocumentContextGap[];
/** Syntax scopes supplied by the context plugin, as zero-based half-open line ranges. */
readonly contextScopes?: {
readonly original: readonly (readonly [number, number])[];
readonly modified: readonly (readonly [number, number])[];
};
readonly sourceLineAlignment?: readonly (readonly [number | null, number | null])[];
/**
* If true, both text models are identical (byte-wise).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,29 @@ export function lensContextGaps(diff: IDocumentDiff, originalCount: number, modi
}));
// Context follows alignment rows, keeping both sides synchronized around insertions.
const context = visible.map((_, index) => visible.slice(Math.max(0, index - 3), index + 4).some(Boolean));
if (diff.contextScopes) {
// A lens must not clip context that diffr kept around its selected code.
// Seed enclosing scope boundaries, then retain each visible context run
// touching a seed. Never expand through a collapsed provider band.
const scopes = [diff.contextScopes.original, diff.contextScopes.modified];
const enclosing = scopes.map((sideScopes, side) => sideScopes.filter(([start, end]) =>
rows.some((row, index) => visible[index] && row[side] !== null && row[side]! >= start && row[side]! < end)));
const open = rows.map(row => row.every((line, side) => line === null || !(diff.contextGaps ?? []).some(gap => {
if (gap.collapsed === false) return false;
const start = side === 0 ? gap.originalStart : gap.modifiedStart;
const count = side === 0 ? gap.originalCount : gap.modifiedCount;
return line + 1 >= start && line + 1 < start + count;
})));
const seeds = rows.map((row, index) => visible[index] || row.some((line, side) =>
line !== null && enclosing[side].some(([start, end]) => line === start || line === end - 1)));
for (let start = 0; start < rows.length;) {
if (!open[start]) { start++; continue; }
let end = start + 1;
while (end < rows.length && open[end]) end++;
if (seeds.slice(start, end).some(Boolean)) context.fill(true, start, end);
start = end;
}
}
const gaps: IDocumentContextGap[] = [];
let left = 1, right = 1;
for (let index = 0; index < rows.length;) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,24 @@ export function regionLines(region: StructuralRegion): { start: number; end: num
return { start: region.start.line, end: region.end.column === 0 ? region.end.line : region.end.line + 1 };
}

/** Preserve the context plugin's scope boundaries for lens projection. */
export function structuralContextScopes(diff: StructuralTextDiff) {
const scopes = (source: StructuralSource | undefined) => {
const result: [number, number][] = [];
const visit = (region: StructuralRegion) => {
if (region.kind !== "fold") return;
if (region.tags?.includes("context:scope")) {
const { start, end } = regionLines(region);
result.push([start, end]);
}
region.children.forEach(visit);
};
source?.regions?.forEach(visit);
return result;
};
return { original: scopes(diff.lhs), modified: scopes(diff.rhs) };
}

export function structuralLeaves(regions: readonly StructuralRegion[] | undefined): StructuralLeaf[] {
const leaves: StructuralLeaf[] = [];
const walk = (region: StructuralRegion) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { autorun, derived, type IObservable } from "../../base/common/observable
import type { UnchangedRegion } from "../../editor/browser/widget/diffEditor/diffEditorViewModel.js";
import {
structuralContextGaps,
structuralContextScopes,
structuralRows,
structuralHighlights,
} from "../common/whiteboardStructuralDiff.js";
Expand Down Expand Up @@ -122,6 +123,7 @@ export class StructuralDiffProvider implements IDocumentDiffProvider {
identical: left === right,
quitEarly: false,
sourceLineAlignment: rows,
contextScopes: structuralContextScopes(diff),
// Every collapsed region is a hidden-region band, labelled by the wire.
contextGaps: structuralContextGaps(
diff,
Expand Down
Loading