Skip to content

Commit

Permalink
add baseline for linked editing (microsoft#54315)
Browse files Browse the repository at this point in the history
  • Loading branch information
iisaduan authored May 26, 2023
1 parent 544d432 commit ca0fafd
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 90 deletions.
67 changes: 67 additions & 0 deletions src/harness/fourslashImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3586,6 +3586,73 @@ export class TestState {
}
}

public baselineLinkedEditing(): void {
const baselineFile = this.getBaselineFileNameForContainingTestFile(".linkedEditing.txt");
const files = this.testData.files;

let baselineContent = "";
let offset = 0;
for (const f of files) {
const result = getLinkedEditingBaselineWorker(f, offset, this.languageService);
baselineContent += result.baselineContent + `\n\n\n`;
offset = result.offset;
}

Harness.Baseline.runBaseline(baselineFile, baselineContent);

function getLinkedEditingBaselineWorker(activeFile: FourSlashFile, offset: number, languageService: ts.LanguageService) {
const fileName = activeFile.fileName;
let baselineContent = `=== ${fileName} ===\n`;

// get linkedEdit at every position in the file, then group positions by their linkedEdit
const linkedEditsInFile = new Map<string, number[]>();
for(let pos = 0; pos < activeFile.content.length; pos++) {
const linkedEditAtPosition = languageService.getLinkedEditingRangeAtPosition(fileName, pos);
if (!linkedEditAtPosition) continue;

const linkedEditString = JSON.stringify(linkedEditAtPosition);
const existingPositions = linkedEditsInFile.get(linkedEditString) ?? [];
linkedEditsInFile.set(linkedEditString, [...existingPositions, pos]);
}

const linkedEditsByRange = [...linkedEditsInFile.entries()].sort((a, b) => a[1][0] - b[1][0]);
if (linkedEditsByRange.length === 0) {
return { baselineContent: baselineContent + activeFile.content + `\n\n--No linked edits found--`, offset };
}

let inlineLinkedEditBaselines: { start: number, end: number, index: number }[] = [];
let linkedEditInfoBaseline = "";
for (const edit of linkedEditsByRange) {
const [linkedEdit, positions] = edit;
let rangeStart = 0;
for (let j = 0; j < positions.length - 1; j++) {
// for each distinct range in the list of positions, add an entry to the list of places that need to be annotated in the baseline
if (positions[j] + 1 !== positions[j + 1]) {
inlineLinkedEditBaselines.push({ start: positions[rangeStart], end: positions[j], index: offset });
rangeStart = j + 1;
}
}
inlineLinkedEditBaselines.push({ start: positions[rangeStart], end: positions[positions.length - 1], index: offset });

// add the LinkedEditInfo with its index to the baseline
linkedEditInfoBaseline += `\n\n=== ${offset} ===\n` + linkedEdit;
offset++;
}

inlineLinkedEditBaselines = inlineLinkedEditBaselines.sort((a, b) => a.start - b.start);
const fileText = activeFile.content;
baselineContent += fileText.slice(0, inlineLinkedEditBaselines[0].start);
for (let i = 0; i < inlineLinkedEditBaselines.length; i++) {
const e = inlineLinkedEditBaselines[i];
const sliceEnd = inlineLinkedEditBaselines[i + 1]?.start;
baselineContent += `[|/*${e.index}*/` + fileText.slice(e.start, e.end) + `|]` + fileText.slice(e.end, sliceEnd);
}

baselineContent += linkedEditInfoBaseline;
return { baselineContent, offset };
}
}

public verifyMatchingBracePosition(bracePosition: number, expectedMatchPosition: number) {
const actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition);

Expand Down
4 changes: 4 additions & 0 deletions src/harness/fourslashInterfaceImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ export class VerifyNegatable {
this.state.verifyLinkedEditingRange(map);
}

public baselineLinkedEditing(): void {
this.state.baselineLinkedEditing();
}

public isInCommentAtPosition(onlyMultiLineDiverges?: boolean) {
this.state.verifySpanOfEnclosingComment(this.negative, onlyMultiLineDiverges);
}
Expand Down
97 changes: 97 additions & 0 deletions tests/baselines/reference/linkedEditingJsxTag10.linkedEditing.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
=== /jsx0.tsx ===
const jsx = <>

--No linked edits found--


=== /jsx1.tsx ===
const jsx = </>

--No linked edits found--


=== /jsx2.tsx ===
const jsx = <div>

--No linked edits found--


=== /jsx3.tsx ===
const jsx = </div>

--No linked edits found--


=== /jsx4.tsx ===
const jsx = <div> </>;

--No linked edits found--


=== /jsx5.tsx ===
const jsx = <> </div>;

--No linked edits found--


=== /jsx6.tsx ===
const jsx = div> </div>;

--No linked edits found--


=== /jsx7.tsx ===
const jsx = <div> /div>;

--No linked edits found--


=== /jsx8.tsx ===
const jsx = <div </div>;

--No linked edits found--


=== /jsx9.tsx ===
const jsx = <[|/*0*/div|]> </[|/*0*/div|];

=== 0 ===
{"ranges":[{"start":13,"length":3},{"start":20,"length":3}],"wordPattern":"[a-zA-Z0-9:\\-\\._$]*"}


=== /jsx10.tsx ===
const jsx = <> </;

--No linked edits found--


=== /jsx11.tsx ===
const jsx = < </>;

--No linked edits found--


=== /jsx12.tsx ===
const jsx = > </>;

--No linked edits found--


=== /jsx13.tsx ===
const jsx = <> />;

--No linked edits found--


=== /jsx14.tsx ===
const jsx = <> <div> </> </div>;

--No linked edits found--


=== /jsx15.tsx ===
const jsx = <div> <> </div> </>;

--No linked edits found--


27 changes: 27 additions & 0 deletions tests/baselines/reference/linkedEditingJsxTag11.linkedEditing.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
=== /customElements.tsx ===
const jsx = <[|/*0*/fbt:enum|] knownProp="accepted"
unknownProp="rejected">
</[|/*0*/fbt:enum|]>;

const customElement = <[|/*1*/custom-element|]></[|/*1*/custom-element|]>;

const standardElement =
<[|/*2*/Link|] href="/hello" passHref>
<[|/*3*/Button|] component="a">
Next
</[|/*3*/Button|]>
</[|/*2*/Link|]>;

=== 0 ===
{"ranges":[{"start":13,"length":8},{"start":73,"length":8}],"wordPattern":"[a-zA-Z0-9:\\-\\._$]*"}

=== 1 ===
{"ranges":[{"start":108,"length":14},{"start":125,"length":14}],"wordPattern":"[a-zA-Z0-9:\\-\\._$]*"}

=== 2 ===
{"ranges":[{"start":172,"length":4},{"start":269,"length":4}],"wordPattern":"[a-zA-Z0-9:\\-\\._$]*"}

=== 3 ===
{"ranges":[{"start":209,"length":6},{"start":256,"length":6}],"wordPattern":"[a-zA-Z0-9:\\-\\._$]*"}


1 change: 1 addition & 0 deletions tests/cases/fourslash/fourslash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ declare namespace FourSlashInterface {
isValidBraceCompletionAtPosition(openingBrace?: string): void;
jsxClosingTag(map: { [markerName: string]: { readonly newText: string } | undefined }): void;
linkedEditing(map: { [markerName: string]: LinkedEditingInfo | undefined }): void;
baselineLinkedEditing(): void;
isInCommentAtPosition(onlyMultiLineDiverges?: boolean): void;
codeFix(options: {
description: string | [string, ...(string | number)[]] | DiagnosticIgnoredInterpolations,
Expand Down
83 changes: 43 additions & 40 deletions tests/cases/fourslash/linkedEditingJsxTag10.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,43 +48,46 @@
// @Filename: /jsx15.tsx
////const jsx = </*15*/div> </*15a*/> <//*15b*/div> <//*15c*/>;

const wordPattern = "[a-zA-Z0-9:\\-\\._$]*";
const linkedCursors9 = {
ranges: [{ start: test.markerByName("9").position, length: 3 }, { start: test.markerByName("9a").position, length: 3 }],
wordPattern,
};

verify.linkedEditing( {
"0": undefined,
"1": undefined,
"2": undefined,
"3": undefined,
"4": undefined,
"4a": undefined,
"5": undefined,
"5a": undefined,
"6": undefined,
"6a": undefined,
"7": undefined,
"7a": undefined,
"8": undefined,
"8a": undefined,
"9": linkedCursors9,
"9a": linkedCursors9,
"10": undefined,
"10a": undefined,
"11": undefined,
"11a": undefined,
"12": undefined,
"12a": undefined,
"13": undefined,
"13a": undefined,
"14": undefined,
"14a": undefined,
"14b": undefined,
"14c": undefined,
"15": undefined,
"15a": undefined,
"15b": undefined,
"15c": undefined,
});
verify.baselineLinkedEditing();

// below is the expected result

// const wordPattern = "[a-zA-Z0-9:\\-\\._$]*";
// const linkedCursors9 = {
// ranges: [{ start: test.markerByName("9").position, length: 3 }, { start: test.markerByName("9a").position, length: 3 }],
// wordPattern,
// };
// verify.linkedEditing( {
// "0": undefined,
// "1": undefined,
// "2": undefined,
// "3": undefined,
// "4": undefined,
// "4a": undefined,
// "5": undefined,
// "5a": undefined,
// "6": undefined,
// "6a": undefined,
// "7": undefined,
// "7a": undefined,
// "8": undefined,
// "8a": undefined,
// "9": linkedCursors9,
// "9a": linkedCursors9,
// "10": undefined,
// "10a": undefined,
// "11": undefined,
// "11a": undefined,
// "12": undefined,
// "12a": undefined,
// "13": undefined,
// "13a": undefined,
// "14": undefined,
// "14a": undefined,
// "14b": undefined,
// "14c": undefined,
// "15": undefined,
// "15a": undefined,
// "15b": undefined,
// "15c": undefined,
// });
58 changes: 8 additions & 50 deletions tests/cases/fourslash/linkedEditingJsxTag11.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,19 @@
/// <reference path='fourslash.ts' />

// for readability
////const jsx = (
//// <div style={{ color: 'red' }}>
//// <p>
//// <img />
//// </p>
//// </div>
////);

// @Filename: /customElements.tsx
//// const jsx = </*1*/fbt/*2*/:en/*3*/um knownProp="accepted"
//// const jsx = <fbt:enum knownProp="accepted"
//// unknownProp="rejected">
//// </f/*4*/bt:e/*5*/num>;
//// </fbt:enum>;
////
//// const customElement = </*6*/custom/*7*/-element/*8*/></custom/*9*/-element>;
//// const customElement = <custom-element></custom-element>;
////
//// const standardElement =
//// </*10*/Link/*11*/ href="/hello" passHref>
//// </*12*/But/*13*/ton component="a">
//// <Link href="/hello" passHref>
//// <Button component="a">
//// Next
//// </But/*14*/ton>
//// </Li/*15*/nk>;
//// </Button>
//// </Link>;

const wordPattern = "[a-zA-Z0-9:\\-\\._$]*";

const linkedCursors1 = {
ranges: [{ start: test.markerByName("1").position, length: 8 }, { start: test.markerByName("4").position - 1, length: 8 }],
wordPattern,
};
const linkedCursors2 = {
ranges: [{ start: test.markerByName("6").position, length: 14 }, { start: test.markerByName("9").position - 6, length: 14 }],
wordPattern,
};
const linkedCursors3 = {
ranges: [{ start: test.markerByName("10").position, length: 4 }, { start: test.markerByName("15").position - 2, length: 4 }],
wordPattern,
};
const linkedCursors4 = {
ranges: [{ start: test.markerByName("12").position, length: 6 }, { start: test.markerByName("14").position - 3, length: 6 }],
wordPattern,
};

verify.linkedEditing( {
"1": linkedCursors1,
"2": linkedCursors1,
"3": linkedCursors1,
"4": linkedCursors1,
"5": linkedCursors1,
"6": linkedCursors2,
"7": linkedCursors2,
"8": linkedCursors2,
"9": linkedCursors2,
"10": linkedCursors3,
"11": linkedCursors3,
"12": linkedCursors4,
"13": linkedCursors4,
"14": linkedCursors4,
"15": linkedCursors3,
});
verify.baselineLinkedEditing();

0 comments on commit ca0fafd

Please sign in to comment.