add baseline for linked editing (#54315)

This commit is contained in:
Isabel Duan 2023-05-26 16:01:29 -07:00 committed by GitHub
parent 544d43286a
commit ca0fafd694
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 246 additions and 89 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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--

View File

@ -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:\\-\\._$]*"}

View File

@ -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,

View File

@ -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.baselineLinkedEditing();
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,
});
// 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,
// });

View File

@ -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();