From 4925fe968a9f65f324e7229082b48389bcd4cc60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Thu, 18 Apr 2024 11:32:33 -0700 Subject: [PATCH 01/15] codemapper support disable synchronization for now Update src/server/session.ts Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Update src/services/mapCode.ts Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Update src/services/mapCode.ts Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Update src/services/mapCode.ts Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> format some review changes more review fixes review more passing tests rejigger how class member replacement works to match statements algo starting baseline-based mapcode tests baseline-based tests review bring back synchronizeHostData syntax operation change move to operating on one file at a time Update src/server/protocol.ts Co-authored-by: Sheetal Nandi Update src/server/protocol.ts Co-authored-by: Sheetal Nandi Update src/server/protocol.ts Co-authored-by: Sheetal Nandi Update src/server/protocol.ts Co-authored-by: Sheetal Nandi Update src/server/protocol.ts Co-authored-by: Sheetal Nandi Update src/server/session.ts Co-authored-by: Sheetal Nandi Update src/server/session.ts Co-authored-by: Sheetal Nandi Update src/services/mapCode.ts Co-authored-by: Sheetal Nandi Update src/services/types.ts Co-authored-by: Sheetal Nandi Update src/services/mapCode.ts Co-authored-by: Sheetal Nandi more review fixes --- src/harness/client.ts | 2 + src/harness/fourslashImpl.ts | 26 ++ src/harness/fourslashInterfaceImpl.ts | 4 + src/server/protocol.ts | 33 ++ src/server/session.ts | 23 ++ src/services/_namespaces/ts.MapCode.ts | 3 + src/services/_namespaces/ts.ts | 2 + src/services/mapCode.ts | 330 ++++++++++++++++++ src/services/services.ts | 13 + src/services/types.ts | 9 + tests/baselines/reference/api/typescript.d.ts | 42 +++ .../mapCodeClassInvalidClassMember.mapCode.ts | 18 + ...mapCodeFocusLocationReplacement.mapCode.ts | 63 ++++ .../mapCodeMethodInsertion.mapCode.ts | 37 ++ .../mapCodeMethodReplacement.mapCode.ts | 34 ++ .../mapCodeMixedClassDeclaration.mapCode.ts | 34 ++ .../mapCodeNestedClassIfInsertion.mapCode.ts | 41 +++ ...mapCodeNestedClassIfReplacement.mapCode.ts | 38 ++ .../mapCodeNestedForInsertion.mapCode.ts | 33 ++ .../mapCodeNestedForOfInsertion.mapCode.ts | 29 ++ .../mapCodeNestedForOfReplacement.mapCode.ts | 25 ++ .../mapCodeNestedForReplacement.mapCode.ts | 25 ++ .../mapCodeNestedIfInsertion.mapCode.ts | 33 ++ .../mapCodeNestedIfReplace.mapCode.ts | 29 ++ .../mapCodeNestedLabeledInsertion.mapCode.ts | 37 ++ .../mapCodeNestedLabeledReplace.mapCode.ts | 32 ++ .../mapCodeNestedWhileInsertion.mapCode.ts | 33 ++ .../mapCodeNestedWhileReplace.mapCode.ts | 29 ++ .../mapCodeRangeReplacement.mapCode.ts | 43 +++ .../mapCodeToplevelInsert.mapCode.ts | 24 ++ .../mapCodeToplevelReplace.mapCode.ts | 22 ++ tests/cases/fourslash/fourslash.ts | 15 + .../mapCodeClassInvalidClassMember.ts | 13 + .../mapCodeFocusLocationReplacement.ts | 38 ++ .../cases/fourslash/mapCodeMethodInsertion.ts | 23 ++ .../fourslash/mapCodeMethodReplacement.ts | 23 ++ .../fourslash/mapCodeMixedClassDeclaration.ts | 25 ++ .../mapCodeNestedClassIfInsertion.ts | 25 ++ .../mapCodeNestedClassIfReplacement.ts | 25 ++ .../fourslash/mapCodeNestedForInsertion.ts | 21 ++ .../fourslash/mapCodeNestedForOfInsertion.ts | 19 + .../mapCodeNestedForOfReplacement.ts | 19 + .../fourslash/mapCodeNestedForReplacement.ts | 19 + .../fourslash/mapCodeNestedIfInsertion.ts | 21 ++ .../cases/fourslash/mapCodeNestedIfReplace.ts | 21 ++ .../mapCodeNestedLabeledInsertion.ts | 23 ++ .../fourslash/mapCodeNestedLabeledReplace.ts | 23 ++ .../fourslash/mapCodeNestedWhileInsertion.ts | 21 ++ .../fourslash/mapCodeNestedWhileReplace.ts | 21 ++ .../fourslash/mapCodeRangeReplacement.ts | 32 ++ .../cases/fourslash/mapCodeToplevelInsert.ts | 16 + .../cases/fourslash/mapCodeToplevelReplace.ts | 17 + 52 files changed, 1606 insertions(+) create mode 100644 src/services/_namespaces/ts.MapCode.ts create mode 100644 src/services/mapCode.ts create mode 100644 tests/baselines/reference/mapCodeClassInvalidClassMember.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeFocusLocationReplacement.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeMethodInsertion.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeMethodReplacement.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeMixedClassDeclaration.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNestedClassIfInsertion.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNestedClassIfReplacement.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNestedForInsertion.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNestedForOfInsertion.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNestedForOfReplacement.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNestedForReplacement.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNestedIfInsertion.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNestedIfReplace.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNestedLabeledInsertion.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNestedLabeledReplace.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNestedWhileInsertion.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNestedWhileReplace.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeRangeReplacement.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeToplevelInsert.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeToplevelReplace.mapCode.ts create mode 100644 tests/cases/fourslash/mapCodeClassInvalidClassMember.ts create mode 100644 tests/cases/fourslash/mapCodeFocusLocationReplacement.ts create mode 100644 tests/cases/fourslash/mapCodeMethodInsertion.ts create mode 100644 tests/cases/fourslash/mapCodeMethodReplacement.ts create mode 100644 tests/cases/fourslash/mapCodeMixedClassDeclaration.ts create mode 100644 tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts create mode 100644 tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts create mode 100644 tests/cases/fourslash/mapCodeNestedForInsertion.ts create mode 100644 tests/cases/fourslash/mapCodeNestedForOfInsertion.ts create mode 100644 tests/cases/fourslash/mapCodeNestedForOfReplacement.ts create mode 100644 tests/cases/fourslash/mapCodeNestedForReplacement.ts create mode 100644 tests/cases/fourslash/mapCodeNestedIfInsertion.ts create mode 100644 tests/cases/fourslash/mapCodeNestedIfReplace.ts create mode 100644 tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts create mode 100644 tests/cases/fourslash/mapCodeNestedLabeledReplace.ts create mode 100644 tests/cases/fourslash/mapCodeNestedWhileInsertion.ts create mode 100644 tests/cases/fourslash/mapCodeNestedWhileReplace.ts create mode 100644 tests/cases/fourslash/mapCodeRangeReplacement.ts create mode 100644 tests/cases/fourslash/mapCodeToplevelInsert.ts create mode 100644 tests/cases/fourslash/mapCodeToplevelReplace.ts diff --git a/src/harness/client.ts b/src/harness/client.ts index a2fa6c4e1d37c..2d764ad15d9d6 100644 --- a/src/harness/client.ts +++ b/src/harness/client.ts @@ -789,6 +789,8 @@ export class SessionClient implements LanguageService { }); } + mapCode = notImplemented; + private createFileLocationOrRangeRequestArgs(positionOrRange: number | TextRange, fileName: string): protocol.FileLocationOrRangeRequestArgs { return typeof positionOrRange === "number" ? this.createFileLocationRequestArgs(fileName, positionOrRange) diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 6c7a14535d2c5..8dd9884255f75 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -4510,6 +4510,32 @@ export class TestState { this.verifyCurrentFileContent(newFileContent); } + + public baselineMapCode( + { fileName, pos }: Range, + changesFilename = "/incomingChanges", + ): void { + const changes = this.getFileContent(changesFilename); + const beforeContents = this.getFileContent(fileName); + const before = beforeContents.slice(0, pos) + "[||]" + beforeContents.slice(pos); + const edits = this.languageService.mapCode( + fileName, + [changes], + [[{ start: pos, length: 1 }]], + this.formatCodeSettings, + {}, + ); + this.applyChanges(edits); + const after = this.getFileContent(fileName); + const baseline = ` +// === ORIGINAL === +${before} +// === INCOMING CHANGES === +${changes} +// === MAPPED === +${after}`; + this.baseline("mapCode", baseline, ".mapCode.ts"); + } } function updateTextRangeForTextChanges({ pos, end }: ts.TextRange, textChanges: readonly ts.TextChange[]): ts.TextRange { diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 28cfa8c201d7d..a2ce5d8cd0330 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -239,6 +239,10 @@ export class VerifyNegatable { public uncommentSelection(newFileContent: string) { this.state.uncommentSelection(newFileContent); } + + public baselineMapCode(range: FourSlash.Range, changesFilename?: string): void { + this.state.baselineMapCode(range, changesFilename); + } } export class Verify extends VerifyNegatable { diff --git a/src/server/protocol.ts b/src/server/protocol.ts index e8d5b285811f5..05a3bf9ab6d9d 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -200,6 +200,7 @@ export const enum CommandTypes { ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls", ProvideInlayHints = "provideInlayHints", WatchChange = "watchChange", + MapCode = "mapCode", } /** @@ -2342,6 +2343,38 @@ export interface InlayHintsResponse extends Response { body?: InlayHintItem[]; } +export interface MapCodeRequestArgs extends FileRequestArgs { + /** + * The files and changes to try and apply/map. + */ + mapping: MapCodeRequestDocumentMapping; +} + +export interface MapCodeRequestDocumentMapping { + /** + * The specific code to map/insert/replace in the file. + */ + contents: string[]; + + /** + * Areas of "focus" to inform the code mapper with. For example, cursor + * location, current selection, viewport, etc. Nested arrays denote + * priority: toplevel arrays are more important than inner arrays, and + * inner array priorities are based on items within that array. Items + * earlier in the arrays have higher priority. + */ + focusLocations?: TextSpan[][]; +} + +export interface MapCodeRequest extends FileRequest { + command: CommandTypes.MapCode; + arguments: MapCodeRequestArgs; +} + +export interface MapCodeResponse extends Response { + body: readonly FileCodeEdits[]; +} + /** * Synchronous request for semantic diagnostics of one file. */ diff --git a/src/server/session.ts b/src/server/session.ts index ff0a02be5b915..1d3b34d66f719 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1906,6 +1906,26 @@ export class Session implements EventSender { }); } + private mapCode(args: protocol.MapCodeRequestArgs): protocol.FileCodeEdits[] { + const formatOptions = this.getHostFormatOptions(); + const preferences = this.getHostPreferences(); + const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; + const focusLocations = args.mapping.focusLocations?.map(spans => { + return spans.map(loc => { + const start = scriptInfo.lineOffsetToPosition(loc.start.line, loc.start.offset); + const end = scriptInfo.lineOffsetToPosition(loc.end.line, loc.end.offset); + return { + start, + length: end - start, + }; + }); + }); + + const changes = languageService.mapCode(file, args.mapping.contents, focusLocations, formatOptions, preferences); + return this.mapTextChangesToCodeEdits(changes); + } + private setCompilerOptionsForInferredProjects(args: protocol.SetCompilerOptionsForInferredProjectsArgs): void { this.projectService.setCompilerOptionsForInferredProjects(args.options, args.projectRootPath); } @@ -3610,6 +3630,9 @@ export class Session implements EventSender { [protocol.CommandTypes.ProvideInlayHints]: (request: protocol.InlayHintsRequest) => { return this.requiredResponse(this.provideInlayHints(request.arguments)); }, + [protocol.CommandTypes.MapCode]: (request: protocol.MapCodeRequest) => { + return this.requiredResponse(this.mapCode(request.arguments)); + }, })); public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse) { diff --git a/src/services/_namespaces/ts.MapCode.ts b/src/services/_namespaces/ts.MapCode.ts new file mode 100644 index 0000000000000..1ef9ddd0f1283 --- /dev/null +++ b/src/services/_namespaces/ts.MapCode.ts @@ -0,0 +1,3 @@ +/* Generated file to emulate the ts.MapCode namespace. */ + +export * from "../mapCode.js"; diff --git a/src/services/_namespaces/ts.ts b/src/services/_namespaces/ts.ts index 0c09ffca05e94..b98a2f743cf59 100644 --- a/src/services/_namespaces/ts.ts +++ b/src/services/_namespaces/ts.ts @@ -33,6 +33,8 @@ export { GoToDefinition }; import * as InlayHints from "./ts.InlayHints.js"; export { InlayHints }; import * as JsDoc from "./ts.JsDoc.js"; +import * as MapCode from "./ts.MapCode.js"; +export { MapCode }; export { JsDoc }; import * as NavigateTo from "./ts.NavigateTo.js"; export { NavigateTo }; diff --git a/src/services/mapCode.ts b/src/services/mapCode.ts new file mode 100644 index 0000000000000..3765ca9c28c67 --- /dev/null +++ b/src/services/mapCode.ts @@ -0,0 +1,330 @@ +import { + Block, + ClassElement, + ClassLikeDeclaration, + createSourceFile, + emptyArray, + FileTextChanges, + find, + findAncestor, + findLast, + flatten, + forEach, + formatting, + getTokenAtPosition, + isBlock, + isClassElement, + isClassLike, + isForInOrOfStatement, + isForStatement, + isIfStatement, + isInterfaceDeclaration, + isLabeledStatement, + isNamedDeclaration, + isSourceFile, + isTypeElement, + isWhileStatement, + LanguageServiceHost, + Mutable, + Node, + NodeArray, + or, + ScriptTarget, + some, + SourceFile, + Statement, + SyntaxKind, + textChanges, + TextSpan, + TypeElement, + UserPreferences, +} from "./_namespaces/ts"; +import { ChangeTracker } from "./textChanges.js"; + +/** @internal */ +export function mapCode( + sourceFile: SourceFile, + contents: string[], + focusLocations: TextSpan[][] | undefined, + host: LanguageServiceHost, + formatContext: formatting.FormatContext, + preferences: UserPreferences, +): FileTextChanges[] { + try { + return textChanges.ChangeTracker.with( + { host, formatContext, preferences }, + changeTracker => { + const parsed = contents.map(parse); + const flattenedLocations = focusLocations && flatten(focusLocations); + for (const nodes of parsed) { + placeNodeGroup( + sourceFile, + changeTracker, + nodes, + flattenedLocations, + ); + } + }, + ); + } + catch (e) { + host.error?.(`mapCode: ${e}`); + return emptyArray; + } +} + +/** + * Tries to parse something into either "top-level" statements, or into blocks + * of class-context definitions. + */ +function parse(content: string): NodeArray { + // We're going to speculatively parse different kinds of contexts to see + // which one makes the most sense, and grab the NodeArray from there. Do + // this as lazily as possible. + const nodeKinds = [ + { + parse: () => + createSourceFile( + "__mapcode_content_nodes.ts", + content, + ScriptTarget.Latest, + /*setParentNodes*/ true, + ), + body: (sf: SourceFile) => sf.statements, + }, + { + parse: () => + createSourceFile( + "__mapcode_class_content_nodes.ts", + `class __class {\n${content}\n}`, + ScriptTarget.Latest, + /*setParentNodes*/ true, + ), + body: (cw: SourceFile) => (cw.statements[0] as ClassLikeDeclaration).members, + }, + ]; + + const parsedNodes = []; + for (const { parse, body } of nodeKinds) { + const sourceFile = parse(); + const bod = body(sourceFile); + if (bod.length && sourceFile.parseDiagnostics.length === 0) { + // If we run into a case with no parse errors, this is likely the right kind. + return bod; + } + // We only want to keep the ones that have some kind of body. + else if (bod.length) { + // Otherwise, we'll need to look at others. + parsedNodes.push({ sourceFile, body: bod }); + } + } + // Heuristic: fewer errors = more likely to be the right kind. + const { body } = parsedNodes.sort( + (a, b) => + a.sourceFile.parseDiagnostics.length - + b.sourceFile.parseDiagnostics.length, + )[0]; + return body; +} + +function placeNodeGroup( + originalFile: SourceFile, + changeTracker: ChangeTracker, + changes: NodeArray, + focusLocations?: TextSpan[], +) { + if (isClassElement(changes[0]) || isTypeElement(changes[0])) { + placeClassNodeGroup( + originalFile, + changeTracker, + changes as NodeArray, + focusLocations, + ); + } + else { + placeStatements( + originalFile, + changeTracker, + changes as NodeArray, + focusLocations, + ); + } +} + +function placeClassNodeGroup( + originalFile: SourceFile, + changeTracker: ChangeTracker, + changes: NodeArray | NodeArray, + focusLocations?: TextSpan[], +) { + let classOrInterface; + if (!focusLocations || !focusLocations.length) { + classOrInterface = find(originalFile.statements, or(isClassLike, isInterfaceDeclaration)); + } + else { + classOrInterface = forEach(focusLocations, location => + findAncestor( + getTokenAtPosition(originalFile, location.start), + or(isClassLike, isInterfaceDeclaration), + )); + } + + if (!classOrInterface) { + throw new Error( + "Failed to find a class or interface to map the given code into.", + ); + } + + const firstMatch = classOrInterface.members.find(member => changes.some(change => matchNode(change, member))); + if (firstMatch) { + // can't be undefined here, since we know we have at least one match. + const lastMatch = findLast( + classOrInterface.members as NodeArray, + member => changes.some(change => matchNode(change, member)), + )!; + + forEach(changes, wipeNode); + changeTracker.replaceNodeRangeWithNodes( + originalFile, + firstMatch, + lastMatch, + changes, + ); + return; + } + + forEach(changes, wipeNode); + changeTracker.insertNodesAfter( + originalFile, + classOrInterface.members[classOrInterface.members.length - 1], + changes, + ); +} + +function placeStatements( + originalFile: SourceFile, + changeTracker: ChangeTracker, + changes: NodeArray, + focusLocations?: TextSpan[], +) { + if (!focusLocations?.length) { + changeTracker.insertNodesAtEndOfFile( + originalFile, + changes, + /*blankLineBetween*/ false, + ); + return; + } + + for (const location of focusLocations) { + const scope = findAncestor( + getTokenAtPosition(originalFile, location.start), + (block): block is Block | SourceFile => + or(isBlock, isSourceFile)(block) && + some(block.statements, origStmt => changes.some(newStmt => matchNode(newStmt, origStmt))), + ); + if (scope) { + const start = scope.statements.find(stmt => changes.some(node => matchNode(node, stmt))); + if (start) { + // Can't be undefined here, since we know we have at least one match. + const end = findLast(scope.statements, stmt => changes.some(node => matchNode(node, stmt)))!; + forEach(changes, wipeNode); + changeTracker.replaceNodeRangeWithNodes( + originalFile, + start, + end, + changes, + ); + return; + } + } + } + + let scopeStatements: NodeArray = originalFile.statements; + for (const location of focusLocations) { + const block = findAncestor( + getTokenAtPosition(originalFile, location.start), + isBlock, + ); + if (block) { + scopeStatements = block.statements; + break; + } + } + forEach(changes, wipeNode); + changeTracker.insertNodesAfter( + originalFile, + scopeStatements[scopeStatements.length - 1], + changes, + ); +} + +function matchNode(a: Node, b: Node): boolean { + if (a.kind !== b.kind) { + return false; + } + + if (a.kind === SyntaxKind.Constructor) { + return a.kind === b.kind; + } + + if (isNamedDeclaration(a) && isNamedDeclaration(b)) { + return a.name.getText() === b.name.getText(); + } + + if (isIfStatement(a) && isIfStatement(b)) { + return ( + a.expression.getText() === b.expression.getText() + ); + } + + if (isWhileStatement(a) && isWhileStatement(b)) { + return ( + a.expression.getText() === + b.expression.getText() + ); + } + + if (isForStatement(a) && isForStatement(b)) { + return ( + a.initializer?.getText() === + b.initializer?.getText() && + a.incrementor?.getText() === + b.incrementor?.getText() && + a.condition?.getText() === b.condition?.getText() + ); + } + + if (isForInOrOfStatement(a) && isForInOrOfStatement(b)) { + return ( + a.expression.getText() === + b.expression.getText() && + a.initializer.getText() === + b.initializer.getText() + ); + } + + if (isLabeledStatement(a) && isLabeledStatement(b)) { + // If we're actually labeling/naming something, we should be a bit + // more lenient about when we match, so we don't care what the actual + // related statement is: we just replace. + return a.label.getText() === b.label.getText(); + } + + if (a.getText() === b.getText()) { + return true; + } + + return false; +} + +function wipeNode(node: Mutable) { + resetNodePositions(node); + node.parent = undefined!; +} + +function resetNodePositions(node: Mutable) { + node.pos = -1; + node.end = -1; + node.forEachChild(resetNodePositions); +} diff --git a/src/services/services.ts b/src/services/services.ts index b46a5956dd4e8..bc597547180e0 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -211,6 +211,7 @@ import { LinkedEditingInfo, LiteralType, map, + MapCode, mapDefined, MapLike, mapOneOrMany, @@ -3165,6 +3166,17 @@ export function createLanguageService( return InlayHints.provideInlayHints(getInlayHintsContext(sourceFile, span, preferences)); } + function mapCode(sourceFile: string, contents: string[], focusLocations: TextSpan[][] | undefined, formatOptions: FormatCodeSettings, preferences: UserPreferences = emptyOptions): FileTextChanges[] { + return MapCode.mapCode( + syntaxTreeCache.getCurrentSourceFile(sourceFile), + contents, + focusLocations, + host, + formatting.getFormatContext(formatOptions, host), + preferences, + ); + } + const ls: LanguageService = { dispose, cleanupSemanticCache, @@ -3236,6 +3248,7 @@ export function createLanguageService( provideInlayHints, getSupportedCodeFixes, getPasteEdits, + mapCode, }; switch (languageServiceMode) { diff --git a/src/services/types.ts b/src/services/types.ts index 7d1b10311f85e..eeff286d29ea8 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -683,6 +683,8 @@ export interface LanguageService { getSupportedCodeFixes(fileName?: string): readonly string[]; + /** @internal */ mapCode(fileName: string, contents: string[], focusLocations: TextSpan[][] | undefined, formatOptions: FormatCodeSettings, preferences: UserPreferences, updates?: FileTextChanges[]): readonly FileTextChanges[]; + dispose(): void; getPasteEdits( args: PasteEditsArgs, @@ -1588,6 +1590,13 @@ export interface OutliningSpan { kind: OutliningSpanKind; } +/** @internal */ +export interface MapCodeDocumentMapping { + fileName: string; + focusLocations?: TextSpan[][]; + contents: string[]; +} + export const enum OutliningSpanKind { /** Single or multi-line comments */ Comment = "comment", diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 59692349afdc9..13a2701e05b4e 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -121,6 +121,7 @@ declare namespace ts { ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls", ProvideInlayHints = "provideInlayHints", WatchChange = "watchChange", + MapCode = "mapCode", } /** * A TypeScript Server message @@ -1769,6 +1770,46 @@ declare namespace ts { export interface InlayHintsResponse extends Response { body?: InlayHintItem[]; } + export interface MapCodeRequestArgs { + /** + * The files and changes to try and apply/map. + */ + mappings: MapCodeRequestDocumentMapping[]; + /** + * Edits to apply before performing the mapping. + */ + updates?: FileCodeEdits[]; + } + export interface MapCodeRequestDocumentMapping { + /** + * The file for the request (absolute pathname required). `undefined` + * if specific file is unknown. + */ + file?: string; + /** + * Optional name of project that contains file + */ + projectFileName?: string; + /** + * The specific code to map/insert/replace in the file. + */ + contents: string[]; + /** + * Areas of "focus" to inform the code mapper with. For example, cursor + * location, current selection, viewport, etc. Nested arrays denote + * priority: toplevel arrays are more important than inner arrays, and + * inner array priorities are based on items within that array. Items + * earlier in the arrays have higher priority. + */ + focusLocations?: FileSpan[][]; + } + export interface MapCodeRequest extends Request { + command: CommandTypes.MapCode; + arguments: MapCodeRequestArgs; + } + export interface MapCodeResponse extends Response { + body: FileCodeEdits[]; + } /** * Synchronous request for semantic diagnostics of one file. */ @@ -3469,6 +3510,7 @@ declare namespace ts { private getLinkedEditingRange; private getDocumentHighlights; private provideInlayHints; + private mapCode; private setCompilerOptionsForInferredProjects; private getProjectInfo; private getProjectInfoWorker; diff --git a/tests/baselines/reference/mapCodeClassInvalidClassMember.mapCode.ts b/tests/baselines/reference/mapCodeClassInvalidClassMember.mapCode.ts new file mode 100644 index 0000000000000..10aaee3330526 --- /dev/null +++ b/tests/baselines/reference/mapCodeClassInvalidClassMember.mapCode.ts @@ -0,0 +1,18 @@ +// === mapCode === + +// === ORIGINAL === +class MyClass {[||] +} + +// === INCOMING CHANGES === +if (false) { + return "hello"; +} + +// === MAPPED === +class MyClass { +} + +if (false) { + return "hello"; +} diff --git a/tests/baselines/reference/mapCodeFocusLocationReplacement.mapCode.ts b/tests/baselines/reference/mapCodeFocusLocationReplacement.mapCode.ts new file mode 100644 index 0000000000000..193db003fc193 --- /dev/null +++ b/tests/baselines/reference/mapCodeFocusLocationReplacement.mapCode.ts @@ -0,0 +1,63 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + const x: number = 1; + const y: number = 2; + if (x === y) { + console.log("hello"); + console.log("world"); + } + return 1; +} +function bar() { + const x: number = 1; + const y: number = 2; + if (x === y)[||] { + console.log("x"); + console.log("y"); + } + return 2; +} +function baz() { + const x: number = 1; + const y: number = 2; + if (x === y) { + console.log(x); + console.log(y); + } + return 3; +} + +// === INCOMING CHANGES === +if (x === y) { + return x + y; +} + +// === MAPPED === +function foo() { + const x: number = 1; + const y: number = 2; + if (x === y) { + console.log("hello"); + console.log("world"); + } + return 1; +} +function bar() { + const x: number = 1; + const y: number = 2; + if (x === y) { + return x + y; + } + return 2; +} +function baz() { + const x: number = 1; + const y: number = 2; + if (x === y) { + console.log(x); + console.log(y); + } + return 3; +} diff --git a/tests/baselines/reference/mapCodeMethodInsertion.mapCode.ts b/tests/baselines/reference/mapCodeMethodInsertion.mapCode.ts new file mode 100644 index 0000000000000..a370254451a3e --- /dev/null +++ b/tests/baselines/reference/mapCodeMethodInsertion.mapCode.ts @@ -0,0 +1,37 @@ +// === mapCode === + +// === ORIGINAL === +class MyClass {[||] + x = 1; + foo() { + return 1; + } + bar() { + return 2; + } + baz() { + return 3; + } +} + +// === INCOMING CHANGES === +quux() { + return 4; +} + +// === MAPPED === +class MyClass { + x = 1; + foo() { + return 1; + } + bar() { + return 2; + } + baz() { + return 3; + } + quux() { + return 4; + } +} diff --git a/tests/baselines/reference/mapCodeMethodReplacement.mapCode.ts b/tests/baselines/reference/mapCodeMethodReplacement.mapCode.ts new file mode 100644 index 0000000000000..67277b119faa0 --- /dev/null +++ b/tests/baselines/reference/mapCodeMethodReplacement.mapCode.ts @@ -0,0 +1,34 @@ +// === mapCode === + +// === ORIGINAL === +class MyClass { + x = 1; + foo() { + return 1; + } + bar() {[||] + return 2; + } + baz() { + return 3; + } +} + +// === INCOMING CHANGES === +bar() { + return 'hello'; +} + +// === MAPPED === +class MyClass { + x = 1; + foo() { + return 1; + } + bar() { + return "hello"; + } + baz() { + return 3; + } +} diff --git a/tests/baselines/reference/mapCodeMixedClassDeclaration.mapCode.ts b/tests/baselines/reference/mapCodeMixedClassDeclaration.mapCode.ts new file mode 100644 index 0000000000000..796b9b37e8248 --- /dev/null +++ b/tests/baselines/reference/mapCodeMixedClassDeclaration.mapCode.ts @@ -0,0 +1,34 @@ +// === mapCode === + +// === ORIGINAL === +class MyClass {[||] + x = 1; + foo() { + return 1; + } + bar() { + return 2; + } +} + +// === INCOMING CHANGES === +x = 3; +bar() { + return 'hello'; +} +baz() { + return 3; +} +y = 2; + +// === MAPPED === +class MyClass { + x = 3; + bar() { + return "hello"; + } + baz() { + return 3; + } + y = 2; +} diff --git a/tests/baselines/reference/mapCodeNestedClassIfInsertion.mapCode.ts b/tests/baselines/reference/mapCodeNestedClassIfInsertion.mapCode.ts new file mode 100644 index 0000000000000..0dcf31d7a0bc8 --- /dev/null +++ b/tests/baselines/reference/mapCodeNestedClassIfInsertion.mapCode.ts @@ -0,0 +1,41 @@ +// === mapCode === + +// === ORIGINAL === +class MyClass { + x = 1; + foo() { + return 1; + } + bar() { + if (true)[||] { + return 2; + } + } + baz() { + return 3; + } +} + +// === INCOMING CHANGES === +if (false) { + return "hello"; +} + +// === MAPPED === +class MyClass { + x = 1; + foo() { + return 1; + } + bar() { + if (true) { + return 2; + if (false) { + return "hello"; + } + } + } + baz() { + return 3; + } +} diff --git a/tests/baselines/reference/mapCodeNestedClassIfReplacement.mapCode.ts b/tests/baselines/reference/mapCodeNestedClassIfReplacement.mapCode.ts new file mode 100644 index 0000000000000..44bf9f2bf944d --- /dev/null +++ b/tests/baselines/reference/mapCodeNestedClassIfReplacement.mapCode.ts @@ -0,0 +1,38 @@ +// === mapCode === + +// === ORIGINAL === +class MyClass { + x = 1; + foo() { + return 1; + } + bar() { + if (true) [||]{ + return 2; + } + } + baz() { + return 3; + } +} + +// === INCOMING CHANGES === +if (true) { + return "hello"; +} + +// === MAPPED === +class MyClass { + x = 1; + foo() { + return 1; + } + bar() { + if (true) { + return "hello"; + } + } + baz() { + return 3; + } +} diff --git a/tests/baselines/reference/mapCodeNestedForInsertion.mapCode.ts b/tests/baselines/reference/mapCodeNestedForInsertion.mapCode.ts new file mode 100644 index 0000000000000..fa175a9a5b314 --- /dev/null +++ b/tests/baselines/reference/mapCodeNestedForInsertion.mapCode.ts @@ -0,0 +1,33 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + const x: number = 1; + const y: number = 2; + for (let i = 0; i < 10; i++) [||]{ + console.log("hello"); + console.log("you"); + } + return 1; +} + +// === INCOMING CHANGES === +for (let j = 0; j < 10; j++) { + console.log("goodbye"); + console.log("world"); +} + +// === MAPPED === +function foo() { + const x: number = 1; + const y: number = 2; + for (let i = 0; i < 10; i++) { + console.log("hello"); + console.log("you"); + for (let j = 0; j < 10; j++) { + console.log("goodbye"); + console.log("world"); + } + } + return 1; +} diff --git a/tests/baselines/reference/mapCodeNestedForOfInsertion.mapCode.ts b/tests/baselines/reference/mapCodeNestedForOfInsertion.mapCode.ts new file mode 100644 index 0000000000000..e71d23085d6c0 --- /dev/null +++ b/tests/baselines/reference/mapCodeNestedForOfInsertion.mapCode.ts @@ -0,0 +1,29 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + for (const x of [1, 2, 3])[||] { + console.log("hello"); + console.log("you"); + } + return 1; +} + +// === INCOMING CHANGES === +for (const y of [1, 2, 3]) { + console.log("goodbye"); + console.log("world"); +} + +// === MAPPED === +function foo() { + for (const x of [1, 2, 3]) { + console.log("hello"); + console.log("you"); + for (const y of [1, 2, 3]) { + console.log("goodbye"); + console.log("world"); + } + } + return 1; +} diff --git a/tests/baselines/reference/mapCodeNestedForOfReplacement.mapCode.ts b/tests/baselines/reference/mapCodeNestedForOfReplacement.mapCode.ts new file mode 100644 index 0000000000000..1ba34b4ffdabe --- /dev/null +++ b/tests/baselines/reference/mapCodeNestedForOfReplacement.mapCode.ts @@ -0,0 +1,25 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + for (const x of [1, 2, 3]) [||]{ + console.log("hello"); + console.log("you"); + } + return 1; +} + +// === INCOMING CHANGES === +for (const x of [1, 2, 3]) { + console.log("goodbye"); + console.log("world"); +} + +// === MAPPED === +function foo() { + for (const x of [1, 2, 3]) { + console.log("goodbye"); + console.log("world"); + } + return 1; +} diff --git a/tests/baselines/reference/mapCodeNestedForReplacement.mapCode.ts b/tests/baselines/reference/mapCodeNestedForReplacement.mapCode.ts new file mode 100644 index 0000000000000..1194d4f6d207c --- /dev/null +++ b/tests/baselines/reference/mapCodeNestedForReplacement.mapCode.ts @@ -0,0 +1,25 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + for (let x = 0; x < 10; x++) [||]{ + console.log("hello"); + console.log("you"); + } + return 1; +} + +// === INCOMING CHANGES === +for (let x = 0; x < 10; x++) { + console.log("goodbye"); + console.log("world"); +} + +// === MAPPED === +function foo() { + for (let x = 0; x < 10; x++) { + console.log("goodbye"); + console.log("world"); + } + return 1; +} diff --git a/tests/baselines/reference/mapCodeNestedIfInsertion.mapCode.ts b/tests/baselines/reference/mapCodeNestedIfInsertion.mapCode.ts new file mode 100644 index 0000000000000..2b82da88c7faa --- /dev/null +++ b/tests/baselines/reference/mapCodeNestedIfInsertion.mapCode.ts @@ -0,0 +1,33 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + const x: number = 1; + const y: number = 2; + if (x === y) [||]{ + console.log("hello"); + console.log("you"); + } + return 1; +} + +// === INCOMING CHANGES === +if (y === x) { + console.log("goodbye"); + console.log("world"); +} + +// === MAPPED === +function foo() { + const x: number = 1; + const y: number = 2; + if (x === y) { + console.log("hello"); + console.log("you"); + if (y === x) { + console.log("goodbye"); + console.log("world"); + } + } + return 1; +} diff --git a/tests/baselines/reference/mapCodeNestedIfReplace.mapCode.ts b/tests/baselines/reference/mapCodeNestedIfReplace.mapCode.ts new file mode 100644 index 0000000000000..e3042ffe9c751 --- /dev/null +++ b/tests/baselines/reference/mapCodeNestedIfReplace.mapCode.ts @@ -0,0 +1,29 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + const x: number = 1; + const y: number = 2; + if (x === y) [||]{ + console.log("hello"); + console.log("you"); + } + return 1; +} + +// === INCOMING CHANGES === +if (x === y) { + console.log("goodbye"); + console.log("world"); +} + +// === MAPPED === +function foo() { + const x: number = 1; + const y: number = 2; + if (x === y) { + console.log("goodbye"); + console.log("world"); + } + return 1; +} diff --git a/tests/baselines/reference/mapCodeNestedLabeledInsertion.mapCode.ts b/tests/baselines/reference/mapCodeNestedLabeledInsertion.mapCode.ts new file mode 100644 index 0000000000000..24f89c88646d4 --- /dev/null +++ b/tests/baselines/reference/mapCodeNestedLabeledInsertion.mapCode.ts @@ -0,0 +1,37 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + const x: number = 1; + const y: number = 2; + myLabel: if (x === y) [||]{ + console.log("hello"); + console.log("you"); + break myLabel; + } + return 1; +} + +// === INCOMING CHANGES === +otherLabel: if (y === x) { + console.log("goodbye"); + console.log("world"); + break otherLabel; +} + +// === MAPPED === +function foo() { + const x: number = 1; + const y: number = 2; + myLabel: if (x === y) { + console.log("hello"); + console.log("you"); + break myLabel; + otherLabel: if (y === x) { + console.log("goodbye"); + console.log("world"); + break otherLabel; + } + } + return 1; +} diff --git a/tests/baselines/reference/mapCodeNestedLabeledReplace.mapCode.ts b/tests/baselines/reference/mapCodeNestedLabeledReplace.mapCode.ts new file mode 100644 index 0000000000000..114ce09b8d4c9 --- /dev/null +++ b/tests/baselines/reference/mapCodeNestedLabeledReplace.mapCode.ts @@ -0,0 +1,32 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + const x: number = 1; + const y: number = 2; + myLabel: if (x === y) [||]{ + console.log("hello"); + console.log("you"); + break myLabel; + } + return 1; +} + +// === INCOMING CHANGES === +myLabel: if (y === x) { + console.log("goodbye"); + console.log("world"); + break myLabel; +} + +// === MAPPED === +function foo() { + const x: number = 1; + const y: number = 2; + myLabel: if (y === x) { + console.log("goodbye"); + console.log("world"); + break myLabel; + } + return 1; +} diff --git a/tests/baselines/reference/mapCodeNestedWhileInsertion.mapCode.ts b/tests/baselines/reference/mapCodeNestedWhileInsertion.mapCode.ts new file mode 100644 index 0000000000000..2e6862eadf816 --- /dev/null +++ b/tests/baselines/reference/mapCodeNestedWhileInsertion.mapCode.ts @@ -0,0 +1,33 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + const x: number = 1; + const y: number = 2; + while (x === y) [||]{ + console.log("hello"); + console.log("you"); + } + return 1; +} + +// === INCOMING CHANGES === +while (y === x) { + console.log("goodbye"); + console.log("world"); +} + +// === MAPPED === +function foo() { + const x: number = 1; + const y: number = 2; + while (x === y) { + console.log("hello"); + console.log("you"); + while (y === x) { + console.log("goodbye"); + console.log("world"); + } + } + return 1; +} diff --git a/tests/baselines/reference/mapCodeNestedWhileReplace.mapCode.ts b/tests/baselines/reference/mapCodeNestedWhileReplace.mapCode.ts new file mode 100644 index 0000000000000..d93bdc1e9e23a --- /dev/null +++ b/tests/baselines/reference/mapCodeNestedWhileReplace.mapCode.ts @@ -0,0 +1,29 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + const x: number = 1; + const y: number = 2; + while (x === y) [||]{ + console.log("hello"); + console.log("you"); + } + return 1; +} + +// === INCOMING CHANGES === +while (x === y) { + console.log("goodbye"); + console.log("world"); +} + +// === MAPPED === +function foo() { + const x: number = 1; + const y: number = 2; + while (x === y) { + console.log("goodbye"); + console.log("world"); + } + return 1; +} diff --git a/tests/baselines/reference/mapCodeRangeReplacement.mapCode.ts b/tests/baselines/reference/mapCodeRangeReplacement.mapCode.ts new file mode 100644 index 0000000000000..3d4eb3715f918 --- /dev/null +++ b/tests/baselines/reference/mapCodeRangeReplacement.mapCode.ts @@ -0,0 +1,43 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + return 1; +} +if (foo == bar) { + console.log("hello"); + console.log("you"); +} +[||] +function bar() { + return 2; +} +function baz() { + return 3; +} +while (false) { + console.log("weee"); +} + +// === INCOMING CHANGES === +if (foo == bar) { + console.log("huh"); +} + +function baz() { + return 'baz'; +} + +// === MAPPED === +function foo() { + return 1; +} +if (foo == bar) { + console.log("huh"); +} +function baz() { + return "baz"; +} +while (false) { + console.log("weee"); +} diff --git a/tests/baselines/reference/mapCodeToplevelInsert.mapCode.ts b/tests/baselines/reference/mapCodeToplevelInsert.mapCode.ts new file mode 100644 index 0000000000000..d0f943c45867a --- /dev/null +++ b/tests/baselines/reference/mapCodeToplevelInsert.mapCode.ts @@ -0,0 +1,24 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + return 1; +}[||] +function bar() { + return 2; +} +// === INCOMING CHANGES === +function baz() { + return 3; +} + +// === MAPPED === +function foo() { + return 1; +} +function bar() { + return 2; +} +function baz() { + return 3; +} diff --git a/tests/baselines/reference/mapCodeToplevelReplace.mapCode.ts b/tests/baselines/reference/mapCodeToplevelReplace.mapCode.ts new file mode 100644 index 0000000000000..4e4f6b42e89b0 --- /dev/null +++ b/tests/baselines/reference/mapCodeToplevelReplace.mapCode.ts @@ -0,0 +1,22 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + return 1; +}[||] +function bar() { + return 2; +} + +// === INCOMING CHANGES === +function foo() { + return 3; +} + +// === MAPPED === +function foo() { + return 3; +} +function bar() { + return 2; +} diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index e892d9d98725c..e76d4e4ebb63a 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -212,6 +212,20 @@ declare namespace FourSlashInterface { start: number; end: number; } + export interface TextChange { + span: TextSpan; + newText: string; + } + export interface FileTextChanges { + fileName: string; + textChanges: readonly TextChange[]; + isNewFile?: boolean; + } + export interface MapCodeDocumentMapping { + fileName?: string; + focusLocations?: TextSpan[][]; + contents: string[]; + } class test_ { markers(): Marker[]; markerNames(): string[]; @@ -452,6 +466,7 @@ declare namespace FourSlashInterface { copiedFrom?: { file: string, range: { pos: number, end: number }[] }; } }): void; + baselineMapCode(range: Range, changesFilename?: string): void; } class edit { caretPosition(): Marker; diff --git a/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts b/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts new file mode 100644 index 0000000000000..3b054d2cf46cb --- /dev/null +++ b/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts @@ -0,0 +1,13 @@ +/// + +// @Filename: /incomingChanges +//// if (false) { +//// return "hello"; +//// } +//// +// @Filename: /index.ts +//// class MyClass {[||] +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts b/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts new file mode 100644 index 0000000000000..14ec325e68342 --- /dev/null +++ b/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts @@ -0,0 +1,38 @@ +/// + +// @Filename: /incomingChanges +//// if (x === y) { +//// return x + y; +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// const x: number = 1; +//// const y: number = 2; +//// if (x === y) { +//// console.log("hello"); +//// console.log("world"); +//// } +//// return 1; +//// } +//// function bar() { +//// const x: number = 1; +//// const y: number = 2; +//// if (x === y)[||] { +//// console.log("x"); +//// console.log("y"); +//// } +//// return 2; +//// } +//// function baz() { +//// const x: number = 1; +//// const y: number = 2; +//// if (x === y) { +//// console.log(x); +//// console.log(y); +//// } +//// return 3; +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeMethodInsertion.ts b/tests/cases/fourslash/mapCodeMethodInsertion.ts new file mode 100644 index 0000000000000..83f54ae6712bb --- /dev/null +++ b/tests/cases/fourslash/mapCodeMethodInsertion.ts @@ -0,0 +1,23 @@ +/// + +// @Filename: /incomingChanges +//// quux() { +//// return 4; +//// } +//// +// @Filename: /index.ts +//// class MyClass {[||] +//// x = 1; +//// foo() { +//// return 1; +//// } +//// bar() { +//// return 2; +//// } +//// baz() { +//// return 3; +//// } +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeMethodReplacement.ts b/tests/cases/fourslash/mapCodeMethodReplacement.ts new file mode 100644 index 0000000000000..2fb49e0b9031a --- /dev/null +++ b/tests/cases/fourslash/mapCodeMethodReplacement.ts @@ -0,0 +1,23 @@ +/// + +// @Filename: /incomingChanges +//// bar() { +//// return 'hello'; +//// } +//// +// @Filename: /index.ts +//// class MyClass { +//// x = 1; +//// foo() { +//// return 1; +//// } +//// bar() {[||] +//// return 2; +//// } +//// baz() { +//// return 3; +//// } +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); diff --git a/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts b/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts new file mode 100644 index 0000000000000..3c8de306243be --- /dev/null +++ b/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts @@ -0,0 +1,25 @@ +/// + +// @Filename: /incomingChanges +//// x = 3; +//// bar() { +//// return 'hello'; +//// } +//// baz() { +//// return 3; +//// } +//// y = 2; +//// +// @Filename: /index.ts +//// class MyClass {[||] +//// x = 1; +//// foo() { +//// return 1; +//// } +//// bar() { +//// return 2; +//// } +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts b/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts new file mode 100644 index 0000000000000..485f6d9bdbcdc --- /dev/null +++ b/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts @@ -0,0 +1,25 @@ +/// + +// @Filename: /incomingChanges +//// if (false) { +//// return "hello"; +//// } +//// +// @Filename: /index.ts +//// class MyClass { +//// x = 1; +//// foo() { +//// return 1; +//// } +//// bar() { +//// if (true)[||] { +//// return 2; +//// } +//// } +//// baz() { +//// return 3; +//// } +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts b/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts new file mode 100644 index 0000000000000..092ded7f39229 --- /dev/null +++ b/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts @@ -0,0 +1,25 @@ +/// + +// @Filename: /incomingChanges +//// if (true) { +//// return "hello"; +//// } +//// +// @Filename: /index.ts +//// class MyClass { +//// x = 1; +//// foo() { +//// return 1; +//// } +//// bar() { +//// if (true) [||]{ +//// return 2; +//// } +//// } +//// baz() { +//// return 3; +//// } +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForInsertion.ts b/tests/cases/fourslash/mapCodeNestedForInsertion.ts new file mode 100644 index 0000000000000..1d6502e914aaf --- /dev/null +++ b/tests/cases/fourslash/mapCodeNestedForInsertion.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: /incomingChanges +//// for (let j = 0; j < 10; j++) { +//// console.log("goodbye"); +//// console.log("world"); +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// const x: number = 1; +//// const y: number = 2; +//// for (let i = 0; i < 10; i++) [||]{ +//// console.log("hello"); +//// console.log("you"); +//// } +//// return 1; +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts b/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts new file mode 100644 index 0000000000000..84064dc197d54 --- /dev/null +++ b/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts @@ -0,0 +1,19 @@ +/// + +// @Filename: /incomingChanges +//// for (const y of [1, 2, 3]) { +//// console.log("goodbye"); +//// console.log("world"); +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// for (const x of [1, 2, 3])[||] { +//// console.log("hello"); +//// console.log("you"); +//// } +//// return 1; +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts b/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts new file mode 100644 index 0000000000000..2ecf12583df83 --- /dev/null +++ b/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts @@ -0,0 +1,19 @@ +/// + +// @Filename: /incomingChanges +//// for (const x of [1, 2, 3]) { +//// console.log("goodbye"); +//// console.log("world"); +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// for (const x of [1, 2, 3]) [||]{ +//// console.log("hello"); +//// console.log("you"); +//// } +//// return 1; +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForReplacement.ts b/tests/cases/fourslash/mapCodeNestedForReplacement.ts new file mode 100644 index 0000000000000..131ae92d8c1d3 --- /dev/null +++ b/tests/cases/fourslash/mapCodeNestedForReplacement.ts @@ -0,0 +1,19 @@ +/// + +// @Filename: /incomingChanges +//// for (let x = 0; x < 10; x++) { +//// console.log("goodbye"); +//// console.log("world"); +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// for (let x = 0; x < 10; x++) [||]{ +//// console.log("hello"); +//// console.log("you"); +//// } +//// return 1; +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedIfInsertion.ts b/tests/cases/fourslash/mapCodeNestedIfInsertion.ts new file mode 100644 index 0000000000000..1bdacfdb1ebf7 --- /dev/null +++ b/tests/cases/fourslash/mapCodeNestedIfInsertion.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: /incomingChanges +//// if (y === x) { +//// console.log("goodbye"); +//// console.log("world"); +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// const x: number = 1; +//// const y: number = 2; +//// if (x === y) [||]{ +//// console.log("hello"); +//// console.log("you"); +//// } +//// return 1; +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedIfReplace.ts b/tests/cases/fourslash/mapCodeNestedIfReplace.ts new file mode 100644 index 0000000000000..e07bee4e83949 --- /dev/null +++ b/tests/cases/fourslash/mapCodeNestedIfReplace.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: /incomingChanges +//// if (x === y) { +//// console.log("goodbye"); +//// console.log("world"); +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// const x: number = 1; +//// const y: number = 2; +//// if (x === y) [||]{ +//// console.log("hello"); +//// console.log("you"); +//// } +//// return 1; +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts b/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts new file mode 100644 index 0000000000000..f84713a335474 --- /dev/null +++ b/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts @@ -0,0 +1,23 @@ +/// + +// @Filename: /incomingChanges +//// otherLabel: if (y === x) { +//// console.log("goodbye"); +//// console.log("world"); +//// break otherLabel; +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// const x: number = 1; +//// const y: number = 2; +//// myLabel: if (x === y) [||]{ +//// console.log("hello"); +//// console.log("you"); +//// break myLabel; +//// } +//// return 1; +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts b/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts new file mode 100644 index 0000000000000..cf2b5c6a31aeb --- /dev/null +++ b/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts @@ -0,0 +1,23 @@ +/// + +// @Filename: /incomingChanges +//// myLabel: if (y === x) { +//// console.log("goodbye"); +//// console.log("world"); +//// break myLabel; +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// const x: number = 1; +//// const y: number = 2; +//// myLabel: if (x === y) [||]{ +//// console.log("hello"); +//// console.log("you"); +//// break myLabel; +//// } +//// return 1; +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts b/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts new file mode 100644 index 0000000000000..f5e89f59cd3b4 --- /dev/null +++ b/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: /incomingChanges +//// while (y === x) { +//// console.log("goodbye"); +//// console.log("world"); +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// const x: number = 1; +//// const y: number = 2; +//// while (x === y) [||]{ +//// console.log("hello"); +//// console.log("you"); +//// } +//// return 1; +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedWhileReplace.ts b/tests/cases/fourslash/mapCodeNestedWhileReplace.ts new file mode 100644 index 0000000000000..058ea43d417f4 --- /dev/null +++ b/tests/cases/fourslash/mapCodeNestedWhileReplace.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: /incomingChanges +//// while (x === y) { +//// console.log("goodbye"); +//// console.log("world"); +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// const x: number = 1; +//// const y: number = 2; +//// while (x === y) [||]{ +//// console.log("hello"); +//// console.log("you"); +//// } +//// return 1; +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeRangeReplacement.ts b/tests/cases/fourslash/mapCodeRangeReplacement.ts new file mode 100644 index 0000000000000..8510d5f08dc7e --- /dev/null +++ b/tests/cases/fourslash/mapCodeRangeReplacement.ts @@ -0,0 +1,32 @@ +/// + +// @Filename: /incomingChanges +//// if (foo == bar) { +//// console.log("huh"); +//// } +//// +//// function baz() { +//// return 'baz'; +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// return 1; +//// } +//// if (foo == bar) { +//// console.log("hello"); +//// console.log("you"); +//// } +//// [||] +//// function bar() { +//// return 2; +//// } +//// function baz() { +//// return 3; +//// } +//// while (false) { +//// console.log("weee"); +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeToplevelInsert.ts b/tests/cases/fourslash/mapCodeToplevelInsert.ts new file mode 100644 index 0000000000000..cf542ef07e0ae --- /dev/null +++ b/tests/cases/fourslash/mapCodeToplevelInsert.ts @@ -0,0 +1,16 @@ +/// + +// @Filename: /incomingChanges +//// function baz() { +//// return 3; +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// return 1; +//// }[||] +//// function bar() { +//// return 2; +//// } + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeToplevelReplace.ts b/tests/cases/fourslash/mapCodeToplevelReplace.ts new file mode 100644 index 0000000000000..9ed1aef21c29f --- /dev/null +++ b/tests/cases/fourslash/mapCodeToplevelReplace.ts @@ -0,0 +1,17 @@ +/// + +// @Filename: /incomingChanges +//// function foo() { +//// return 3; +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// return 1; +//// }[||] +//// function bar() { +//// return 2; +//// } +//// + +verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file From 0eaf748248696b85db49a8f7c2a2e830fa34da59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 14 May 2024 12:45:19 -0700 Subject: [PATCH 02/15] accept new baseline --- tests/baselines/reference/api/typescript.d.ts | 23 ++++--------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 13a2701e05b4e..916c5c124b108 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1770,26 +1770,13 @@ declare namespace ts { export interface InlayHintsResponse extends Response { body?: InlayHintItem[]; } - export interface MapCodeRequestArgs { + export interface MapCodeRequestArgs extends FileRequestArgs { /** * The files and changes to try and apply/map. */ - mappings: MapCodeRequestDocumentMapping[]; - /** - * Edits to apply before performing the mapping. - */ - updates?: FileCodeEdits[]; + mapping: MapCodeRequestDocumentMapping; } export interface MapCodeRequestDocumentMapping { - /** - * The file for the request (absolute pathname required). `undefined` - * if specific file is unknown. - */ - file?: string; - /** - * Optional name of project that contains file - */ - projectFileName?: string; /** * The specific code to map/insert/replace in the file. */ @@ -1801,14 +1788,14 @@ declare namespace ts { * inner array priorities are based on items within that array. Items * earlier in the arrays have higher priority. */ - focusLocations?: FileSpan[][]; + focusLocations?: TextSpan[][]; } - export interface MapCodeRequest extends Request { + export interface MapCodeRequest extends FileRequest { command: CommandTypes.MapCode; arguments: MapCodeRequestArgs; } export interface MapCodeResponse extends Response { - body: FileCodeEdits[]; + body: readonly FileCodeEdits[]; } /** * Synchronous request for semantic diagnostics of one file. From dd8f1a9912ebcc4dcbcd0d7c25e768eae4fe1a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 14 May 2024 12:48:06 -0700 Subject: [PATCH 03/15] fix lint error --- src/services/mapCode.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/mapCode.ts b/src/services/mapCode.ts index 3765ca9c28c67..8d8d08a6e4bef 100644 --- a/src/services/mapCode.ts +++ b/src/services/mapCode.ts @@ -38,7 +38,7 @@ import { TextSpan, TypeElement, UserPreferences, -} from "./_namespaces/ts"; +} from "./_namespaces/ts.js"; import { ChangeTracker } from "./textChanges.js"; /** @internal */ From 7a69f27e0ca89900b77910cf74e38864f540a043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 14 May 2024 14:18:50 -0700 Subject: [PATCH 04/15] name baseline files and require passing it in --- src/harness/fourslashImpl.ts | 2 +- src/harness/fourslashInterfaceImpl.ts | 2 +- tests/cases/fourslash/mapCodeClassInvalidClassMember.ts | 4 ++-- tests/cases/fourslash/mapCodeFocusLocationReplacement.ts | 4 ++-- tests/cases/fourslash/mapCodeMethodInsertion.ts | 4 ++-- tests/cases/fourslash/mapCodeMethodReplacement.ts | 4 ++-- tests/cases/fourslash/mapCodeMixedClassDeclaration.ts | 4 ++-- tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts | 4 ++-- tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts | 4 ++-- tests/cases/fourslash/mapCodeNestedForInsertion.ts | 4 ++-- tests/cases/fourslash/mapCodeNestedForOfInsertion.ts | 4 ++-- tests/cases/fourslash/mapCodeNestedForOfReplacement.ts | 4 ++-- tests/cases/fourslash/mapCodeNestedForReplacement.ts | 4 ++-- tests/cases/fourslash/mapCodeNestedIfInsertion.ts | 4 ++-- tests/cases/fourslash/mapCodeNestedIfReplace.ts | 4 ++-- tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts | 4 ++-- tests/cases/fourslash/mapCodeNestedLabeledReplace.ts | 4 ++-- tests/cases/fourslash/mapCodeNestedWhileInsertion.ts | 4 ++-- tests/cases/fourslash/mapCodeNestedWhileReplace.ts | 4 ++-- tests/cases/fourslash/mapCodeRangeReplacement.ts | 4 ++-- tests/cases/fourslash/mapCodeToplevelInsert.ts | 4 ++-- tests/cases/fourslash/mapCodeToplevelReplace.ts | 4 ++-- 22 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 8dd9884255f75..4fb6bc885b961 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -4513,7 +4513,7 @@ export class TestState { public baselineMapCode( { fileName, pos }: Range, - changesFilename = "/incomingChanges", + changesFilename: string, ): void { const changes = this.getFileContent(changesFilename); const beforeContents = this.getFileContent(fileName); diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index a2ce5d8cd0330..c1262a25ada0f 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -240,7 +240,7 @@ export class VerifyNegatable { this.state.uncommentSelection(newFileContent); } - public baselineMapCode(range: FourSlash.Range, changesFilename?: string): void { + public baselineMapCode(range: FourSlash.Range, changesFilename: string): void { this.state.baselineMapCode(range, changesFilename); } } diff --git a/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts b/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts index 3b054d2cf46cb..6d932edf04b47 100644 --- a/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts +++ b/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// if (false) { //// return "hello"; //// } @@ -10,4 +10,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts b/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts index 14ec325e68342..6f7a59c0ff0d7 100644 --- a/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts +++ b/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// if (x === y) { //// return x + y; //// } @@ -35,4 +35,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeMethodInsertion.ts b/tests/cases/fourslash/mapCodeMethodInsertion.ts index 83f54ae6712bb..ce91c8401b85b 100644 --- a/tests/cases/fourslash/mapCodeMethodInsertion.ts +++ b/tests/cases/fourslash/mapCodeMethodInsertion.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// quux() { //// return 4; //// } @@ -20,4 +20,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeMethodReplacement.ts b/tests/cases/fourslash/mapCodeMethodReplacement.ts index 2fb49e0b9031a..1dd1238cb7b11 100644 --- a/tests/cases/fourslash/mapCodeMethodReplacement.ts +++ b/tests/cases/fourslash/mapCodeMethodReplacement.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// bar() { //// return 'hello'; //// } @@ -20,4 +20,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); diff --git a/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts b/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts index 3c8de306243be..1c55f21476be9 100644 --- a/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts +++ b/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// x = 3; //// bar() { //// return 'hello'; @@ -22,4 +22,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts b/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts index 485f6d9bdbcdc..ffb231208984d 100644 --- a/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// if (false) { //// return "hello"; //// } @@ -22,4 +22,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts b/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts index 092ded7f39229..88cdb4c634d76 100644 --- a/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts +++ b/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// if (true) { //// return "hello"; //// } @@ -22,4 +22,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForInsertion.ts b/tests/cases/fourslash/mapCodeNestedForInsertion.ts index 1d6502e914aaf..efe36833b3bbe 100644 --- a/tests/cases/fourslash/mapCodeNestedForInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedForInsertion.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// for (let j = 0; j < 10; j++) { //// console.log("goodbye"); //// console.log("world"); @@ -18,4 +18,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts b/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts index 84064dc197d54..dce3c6e812d17 100644 --- a/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// for (const y of [1, 2, 3]) { //// console.log("goodbye"); //// console.log("world"); @@ -16,4 +16,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts b/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts index 2ecf12583df83..4b6b352def78d 100644 --- a/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts +++ b/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// for (const x of [1, 2, 3]) { //// console.log("goodbye"); //// console.log("world"); @@ -16,4 +16,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForReplacement.ts b/tests/cases/fourslash/mapCodeNestedForReplacement.ts index 131ae92d8c1d3..0bfe1a615bcf2 100644 --- a/tests/cases/fourslash/mapCodeNestedForReplacement.ts +++ b/tests/cases/fourslash/mapCodeNestedForReplacement.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// for (let x = 0; x < 10; x++) { //// console.log("goodbye"); //// console.log("world"); @@ -16,4 +16,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedIfInsertion.ts b/tests/cases/fourslash/mapCodeNestedIfInsertion.ts index 1bdacfdb1ebf7..8c5cdff24e830 100644 --- a/tests/cases/fourslash/mapCodeNestedIfInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedIfInsertion.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// if (y === x) { //// console.log("goodbye"); //// console.log("world"); @@ -18,4 +18,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedIfReplace.ts b/tests/cases/fourslash/mapCodeNestedIfReplace.ts index e07bee4e83949..9f6d1424e5418 100644 --- a/tests/cases/fourslash/mapCodeNestedIfReplace.ts +++ b/tests/cases/fourslash/mapCodeNestedIfReplace.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// if (x === y) { //// console.log("goodbye"); //// console.log("world"); @@ -18,4 +18,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts b/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts index f84713a335474..ab9266d8b8b7d 100644 --- a/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// otherLabel: if (y === x) { //// console.log("goodbye"); //// console.log("world"); @@ -20,4 +20,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts b/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts index cf2b5c6a31aeb..c17ff7e951176 100644 --- a/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts +++ b/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// myLabel: if (y === x) { //// console.log("goodbye"); //// console.log("world"); @@ -20,4 +20,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts b/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts index f5e89f59cd3b4..4e8132b4bfb0d 100644 --- a/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// while (y === x) { //// console.log("goodbye"); //// console.log("world"); @@ -18,4 +18,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedWhileReplace.ts b/tests/cases/fourslash/mapCodeNestedWhileReplace.ts index 058ea43d417f4..eeea214584229 100644 --- a/tests/cases/fourslash/mapCodeNestedWhileReplace.ts +++ b/tests/cases/fourslash/mapCodeNestedWhileReplace.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// while (x === y) { //// console.log("goodbye"); //// console.log("world"); @@ -18,4 +18,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeRangeReplacement.ts b/tests/cases/fourslash/mapCodeRangeReplacement.ts index 8510d5f08dc7e..f94a5ebce6b4a 100644 --- a/tests/cases/fourslash/mapCodeRangeReplacement.ts +++ b/tests/cases/fourslash/mapCodeRangeReplacement.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// if (foo == bar) { //// console.log("huh"); //// } @@ -29,4 +29,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeToplevelInsert.ts b/tests/cases/fourslash/mapCodeToplevelInsert.ts index cf542ef07e0ae..6d2c0663b9aca 100644 --- a/tests/cases/fourslash/mapCodeToplevelInsert.ts +++ b/tests/cases/fourslash/mapCodeToplevelInsert.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// function baz() { //// return 3; //// } @@ -13,4 +13,4 @@ //// return 2; //// } -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeToplevelReplace.ts b/tests/cases/fourslash/mapCodeToplevelReplace.ts index 9ed1aef21c29f..e605c13ddfc41 100644 --- a/tests/cases/fourslash/mapCodeToplevelReplace.ts +++ b/tests/cases/fourslash/mapCodeToplevelReplace.ts @@ -1,6 +1,6 @@ /// -// @Filename: /incomingChanges +// @Filename: /incomingChanges.ts //// function foo() { //// return 3; //// } @@ -14,4 +14,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0]); \ No newline at end of file +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file From 56f87ed4a57670f3d9774664e5b8c4a6f6df7eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 21 May 2024 13:12:41 -0700 Subject: [PATCH 05/15] don't bother trying to map class members if there's no class --- src/services/mapCode.ts | 5 ++--- .../mapCodeToplevelInsertNoClass.mapCode.ts | 21 +++++++++++++++++++ .../fourslash/mapCodeToplevelInsertNoClass.ts | 16 ++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/mapCodeToplevelInsertNoClass.mapCode.ts create mode 100644 tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts diff --git a/src/services/mapCode.ts b/src/services/mapCode.ts index 8d8d08a6e4bef..497e8d5619b92 100644 --- a/src/services/mapCode.ts +++ b/src/services/mapCode.ts @@ -170,9 +170,8 @@ function placeClassNodeGroup( } if (!classOrInterface) { - throw new Error( - "Failed to find a class or interface to map the given code into.", - ); + // No class? don't insert. + return; } const firstMatch = classOrInterface.members.find(member => changes.some(change => matchNode(change, member))); diff --git a/tests/baselines/reference/mapCodeToplevelInsertNoClass.mapCode.ts b/tests/baselines/reference/mapCodeToplevelInsertNoClass.mapCode.ts new file mode 100644 index 0000000000000..87ea9145a0716 --- /dev/null +++ b/tests/baselines/reference/mapCodeToplevelInsertNoClass.mapCode.ts @@ -0,0 +1,21 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + return 1; +}[||] +function bar() { + return 2; +} +// === INCOMING CHANGES === +baz() { + return 3; +} + +// === MAPPED === +function foo() { + return 1; +} +function bar() { + return 2; +} \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts b/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts new file mode 100644 index 0000000000000..67ec6850c839d --- /dev/null +++ b/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts @@ -0,0 +1,16 @@ +/// + +// @Filename: /incomingChanges.ts +//// baz() { +//// return 3; +//// } +//// +// @Filename: /index.ts +//// function foo() { +//// return 1; +//// }[||] +//// function bar() { +//// return 2; +//// } + +verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); From 126479b51f7e3696ad587d7614d135c9bd57eeb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 21 May 2024 13:21:04 -0700 Subject: [PATCH 06/15] remove stale MapCodeMapping interface --- src/services/types.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/services/types.ts b/src/services/types.ts index eeff286d29ea8..6cad8ac448901 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -1590,13 +1590,6 @@ export interface OutliningSpan { kind: OutliningSpanKind; } -/** @internal */ -export interface MapCodeDocumentMapping { - fileName: string; - focusLocations?: TextSpan[][]; - contents: string[]; -} - export const enum OutliningSpanKind { /** Single or multi-line comments */ Comment = "comment", From 054ce2d57264d0f05584adae12123e873e33a5a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 21 May 2024 14:45:22 -0700 Subject: [PATCH 07/15] Test focusLocation with ranges --- src/harness/fourslashImpl.ts | 34 ++++++++++++++++--- src/harness/fourslashInterfaceImpl.ts | 4 +-- .../mapCodeReplaceUsingRange.mapCode.ts | 22 ++++++++++++ tests/cases/fourslash/fourslash.ts | 2 +- .../mapCodeClassInvalidClassMember.ts | 2 +- .../mapCodeFocusLocationReplacement.ts | 2 +- .../cases/fourslash/mapCodeMethodInsertion.ts | 2 +- .../fourslash/mapCodeMethodReplacement.ts | 2 +- .../fourslash/mapCodeMixedClassDeclaration.ts | 2 +- .../mapCodeNestedClassIfInsertion.ts | 2 +- .../mapCodeNestedClassIfReplacement.ts | 2 +- .../fourslash/mapCodeNestedForInsertion.ts | 2 +- .../fourslash/mapCodeNestedForOfInsertion.ts | 2 +- .../mapCodeNestedForOfReplacement.ts | 2 +- .../fourslash/mapCodeNestedForReplacement.ts | 2 +- .../fourslash/mapCodeNestedIfInsertion.ts | 2 +- .../cases/fourslash/mapCodeNestedIfReplace.ts | 2 +- .../mapCodeNestedLabeledInsertion.ts | 2 +- .../fourslash/mapCodeNestedLabeledReplace.ts | 2 +- .../fourslash/mapCodeNestedWhileInsertion.ts | 2 +- .../fourslash/mapCodeNestedWhileReplace.ts | 2 +- .../fourslash/mapCodeRangeReplacement.ts | 2 +- .../fourslash/mapCodeReplaceUsingRange.ts | 17 ++++++++++ .../cases/fourslash/mapCodeToplevelInsert.ts | 2 +- .../fourslash/mapCodeToplevelInsertNoClass.ts | 2 +- .../cases/fourslash/mapCodeToplevelReplace.ts | 2 +- 26 files changed, 93 insertions(+), 28 deletions(-) create mode 100644 tests/baselines/reference/mapCodeReplaceUsingRange.mapCode.ts create mode 100644 tests/cases/fourslash/mapCodeReplaceUsingRange.ts diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 4fb6bc885b961..5c7d576a29a4b 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -4512,16 +4512,42 @@ export class TestState { } public baselineMapCode( - { fileName, pos }: Range, + ranges: Range[], changesFilename: string, ): void { const changes = this.getFileContent(changesFilename); - const beforeContents = this.getFileContent(fileName); - const before = beforeContents.slice(0, pos) + "[||]" + beforeContents.slice(pos); + let fileName: string | undefined; + const focusLocations = ranges.map(({ fileName: fn, pos, end }) => { + if (!fileName) { + fileName = fn; + } + return [{ start: pos, length: end - pos }]; + }); + if (!fileName) { + throw new Error("No ranges passed in, or something went wrong."); + } + let before = this.getFileContent(fileName); + focusLocations.sort((a, b) => a[0].start - b[0].start); + for (const subLoc of focusLocations) { + for (const { start, length } of subLoc) { + let offset = 0; + for (const sl2 of focusLocations) { + for (const { start: s2, length: l2 } of sl2) { + if (s2 < start) { + offset += 4; + if ((s2 + l2) > start) { + offset -= 2; + } + } + } + } + before = before.slice(0, start + offset) + "[|" + before.slice(start + offset, start + offset + length) + "|]" + before.slice(start + offset + length); + } + } const edits = this.languageService.mapCode( fileName, [changes], - [[{ start: pos, length: 1 }]], + focusLocations, this.formatCodeSettings, {}, ); diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index c1262a25ada0f..cc101cc148e58 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -240,8 +240,8 @@ export class VerifyNegatable { this.state.uncommentSelection(newFileContent); } - public baselineMapCode(range: FourSlash.Range, changesFilename: string): void { - this.state.baselineMapCode(range, changesFilename); + public baselineMapCode(ranges: FourSlash.Range[], changesFilename: string): void { + this.state.baselineMapCode(ranges, changesFilename); } } diff --git a/tests/baselines/reference/mapCodeReplaceUsingRange.mapCode.ts b/tests/baselines/reference/mapCodeReplaceUsingRange.mapCode.ts new file mode 100644 index 0000000000000..7afc919ae8aca --- /dev/null +++ b/tests/baselines/reference/mapCodeReplaceUsingRange.mapCode.ts @@ -0,0 +1,22 @@ +// === mapCode === + +// === ORIGINAL === +[|function foo() { + return 1; +}[||] +function bar() { + return [|2;|] +}|] + +// === INCOMING CHANGES === +function foo() { + return 3; +} + +// === MAPPED === +function foo() { + return 3; +} +function bar() { + return 2; +} diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index e76d4e4ebb63a..499df9cced4a1 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -466,7 +466,7 @@ declare namespace FourSlashInterface { copiedFrom?: { file: string, range: { pos: number, end: number }[] }; } }): void; - baselineMapCode(range: Range, changesFilename?: string): void; + baselineMapCode(ranges: Range[], changesFilename?: string): void; } class edit { caretPosition(): Marker; diff --git a/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts b/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts index 6d932edf04b47..0ff05e37b3393 100644 --- a/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts +++ b/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts @@ -10,4 +10,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts b/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts index 6f7a59c0ff0d7..1c01f6065ab25 100644 --- a/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts +++ b/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts @@ -35,4 +35,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeMethodInsertion.ts b/tests/cases/fourslash/mapCodeMethodInsertion.ts index ce91c8401b85b..3f966f7ef7e6d 100644 --- a/tests/cases/fourslash/mapCodeMethodInsertion.ts +++ b/tests/cases/fourslash/mapCodeMethodInsertion.ts @@ -20,4 +20,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeMethodReplacement.ts b/tests/cases/fourslash/mapCodeMethodReplacement.ts index 1dd1238cb7b11..2787d50af95ff 100644 --- a/tests/cases/fourslash/mapCodeMethodReplacement.ts +++ b/tests/cases/fourslash/mapCodeMethodReplacement.ts @@ -20,4 +20,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); diff --git a/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts b/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts index 1c55f21476be9..1b3d306637c52 100644 --- a/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts +++ b/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts @@ -22,4 +22,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts b/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts index ffb231208984d..8f609e16267d0 100644 --- a/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts @@ -22,4 +22,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts b/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts index 88cdb4c634d76..d944d05fa3f16 100644 --- a/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts +++ b/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts @@ -22,4 +22,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForInsertion.ts b/tests/cases/fourslash/mapCodeNestedForInsertion.ts index efe36833b3bbe..09ead4ee37389 100644 --- a/tests/cases/fourslash/mapCodeNestedForInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedForInsertion.ts @@ -18,4 +18,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts b/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts index dce3c6e812d17..4a37e87ec5eab 100644 --- a/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts @@ -16,4 +16,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts b/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts index 4b6b352def78d..32c6414c2f01e 100644 --- a/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts +++ b/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts @@ -16,4 +16,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForReplacement.ts b/tests/cases/fourslash/mapCodeNestedForReplacement.ts index 0bfe1a615bcf2..ced6e5264f425 100644 --- a/tests/cases/fourslash/mapCodeNestedForReplacement.ts +++ b/tests/cases/fourslash/mapCodeNestedForReplacement.ts @@ -16,4 +16,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedIfInsertion.ts b/tests/cases/fourslash/mapCodeNestedIfInsertion.ts index 8c5cdff24e830..1732172c2302e 100644 --- a/tests/cases/fourslash/mapCodeNestedIfInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedIfInsertion.ts @@ -18,4 +18,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedIfReplace.ts b/tests/cases/fourslash/mapCodeNestedIfReplace.ts index 9f6d1424e5418..c3ca1c5fb8366 100644 --- a/tests/cases/fourslash/mapCodeNestedIfReplace.ts +++ b/tests/cases/fourslash/mapCodeNestedIfReplace.ts @@ -18,4 +18,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts b/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts index ab9266d8b8b7d..fc4a87471da41 100644 --- a/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts @@ -20,4 +20,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts b/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts index c17ff7e951176..0e60d329af91a 100644 --- a/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts +++ b/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts @@ -20,4 +20,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts b/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts index 4e8132b4bfb0d..ac98cd69c0f50 100644 --- a/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts @@ -18,4 +18,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedWhileReplace.ts b/tests/cases/fourslash/mapCodeNestedWhileReplace.ts index eeea214584229..7bd21a9698e18 100644 --- a/tests/cases/fourslash/mapCodeNestedWhileReplace.ts +++ b/tests/cases/fourslash/mapCodeNestedWhileReplace.ts @@ -18,4 +18,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeRangeReplacement.ts b/tests/cases/fourslash/mapCodeRangeReplacement.ts index f94a5ebce6b4a..8fddddb6e918e 100644 --- a/tests/cases/fourslash/mapCodeRangeReplacement.ts +++ b/tests/cases/fourslash/mapCodeRangeReplacement.ts @@ -29,4 +29,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeReplaceUsingRange.ts b/tests/cases/fourslash/mapCodeReplaceUsingRange.ts new file mode 100644 index 0000000000000..fb723acc7c835 --- /dev/null +++ b/tests/cases/fourslash/mapCodeReplaceUsingRange.ts @@ -0,0 +1,17 @@ +/// + +// @Filename: /incomingChanges.ts +//// function foo() { +//// return 3; +//// } +//// +// @Filename: /index.ts +//// [|function foo() { +//// return 1; +//// }[||] +//// function bar() { +//// return [|2;|] +//// }|] +//// + +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); diff --git a/tests/cases/fourslash/mapCodeToplevelInsert.ts b/tests/cases/fourslash/mapCodeToplevelInsert.ts index 6d2c0663b9aca..8b0f7b2c431a8 100644 --- a/tests/cases/fourslash/mapCodeToplevelInsert.ts +++ b/tests/cases/fourslash/mapCodeToplevelInsert.ts @@ -13,4 +13,4 @@ //// return 2; //// } -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts b/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts index 67ec6850c839d..9feb70fb13f04 100644 --- a/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts +++ b/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts @@ -13,4 +13,4 @@ //// return 2; //// } -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); diff --git a/tests/cases/fourslash/mapCodeToplevelReplace.ts b/tests/cases/fourslash/mapCodeToplevelReplace.ts index e605c13ddfc41..dc11d2d702e38 100644 --- a/tests/cases/fourslash/mapCodeToplevelReplace.ts +++ b/tests/cases/fourslash/mapCodeToplevelReplace.ts @@ -14,4 +14,4 @@ //// } //// -verify.baselineMapCode(test.ranges()[0], "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file From 8f4a3a090016f8c8f134201fc3847cc0b070b637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 21 May 2024 15:10:30 -0700 Subject: [PATCH 08/15] format --- src/server/protocol.ts | 2 +- src/services/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 05a3bf9ab6d9d..d12c97bdebc32 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2343,7 +2343,7 @@ export interface InlayHintsResponse extends Response { body?: InlayHintItem[]; } -export interface MapCodeRequestArgs extends FileRequestArgs { +export interface MapCodeRequestArgs extends FileRequestArgs { /** * The files and changes to try and apply/map. */ diff --git a/src/services/types.ts b/src/services/types.ts index 6cad8ac448901..8687c9a3138b1 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -683,7 +683,7 @@ export interface LanguageService { getSupportedCodeFixes(fileName?: string): readonly string[]; - /** @internal */ mapCode(fileName: string, contents: string[], focusLocations: TextSpan[][] | undefined, formatOptions: FormatCodeSettings, preferences: UserPreferences, updates?: FileTextChanges[]): readonly FileTextChanges[]; + /** @internal */ mapCode(fileName: string, contents: string[], focusLocations: TextSpan[][] | undefined, formatOptions: FormatCodeSettings, preferences: UserPreferences, updates?: FileTextChanges[]): readonly FileTextChanges[]; dispose(): void; getPasteEdits( From f31560c409ea93fa0f507f6729422a2350eab4f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Wed, 22 May 2024 13:23:43 -0700 Subject: [PATCH 09/15] more review fixes --- src/services/mapCode.ts | 36 +++++++++++++----------------- src/services/services.ts | 2 +- src/services/types.ts | 2 +- tests/cases/fourslash/fourslash.ts | 14 ------------ 4 files changed, 17 insertions(+), 37 deletions(-) diff --git a/src/services/mapCode.ts b/src/services/mapCode.ts index 497e8d5619b92..68c8754914209 100644 --- a/src/services/mapCode.ts +++ b/src/services/mapCode.ts @@ -50,27 +50,21 @@ export function mapCode( formatContext: formatting.FormatContext, preferences: UserPreferences, ): FileTextChanges[] { - try { - return textChanges.ChangeTracker.with( - { host, formatContext, preferences }, - changeTracker => { - const parsed = contents.map(parse); - const flattenedLocations = focusLocations && flatten(focusLocations); - for (const nodes of parsed) { - placeNodeGroup( - sourceFile, - changeTracker, - nodes, - flattenedLocations, - ); - } - }, - ); - } - catch (e) { - host.error?.(`mapCode: ${e}`); - return emptyArray; - } + return textChanges.ChangeTracker.with( + { host, formatContext, preferences }, + changeTracker => { + const parsed = contents.map(parse); + const flattenedLocations = focusLocations && flatten(focusLocations); + for (const nodes of parsed) { + placeNodeGroup( + sourceFile, + changeTracker, + nodes, + flattenedLocations, + ); + } + }, + ); } /** diff --git a/src/services/services.ts b/src/services/services.ts index bc597547180e0..2bd5c94bb0efe 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3166,7 +3166,7 @@ export function createLanguageService( return InlayHints.provideInlayHints(getInlayHintsContext(sourceFile, span, preferences)); } - function mapCode(sourceFile: string, contents: string[], focusLocations: TextSpan[][] | undefined, formatOptions: FormatCodeSettings, preferences: UserPreferences = emptyOptions): FileTextChanges[] { + function mapCode(sourceFile: string, contents: string[], focusLocations: TextSpan[][] | undefined, formatOptions: FormatCodeSettings, preferences: UserPreferences): FileTextChanges[] { return MapCode.mapCode( syntaxTreeCache.getCurrentSourceFile(sourceFile), contents, diff --git a/src/services/types.ts b/src/services/types.ts index 8687c9a3138b1..0dc8b87790260 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -683,7 +683,7 @@ export interface LanguageService { getSupportedCodeFixes(fileName?: string): readonly string[]; - /** @internal */ mapCode(fileName: string, contents: string[], focusLocations: TextSpan[][] | undefined, formatOptions: FormatCodeSettings, preferences: UserPreferences, updates?: FileTextChanges[]): readonly FileTextChanges[]; + /** @internal */ mapCode(fileName: string, contents: string[], focusLocations: TextSpan[][] | undefined, formatOptions: FormatCodeSettings, preferences: UserPreferences): readonly FileTextChanges[]; dispose(): void; getPasteEdits( diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 499df9cced4a1..4eff8b9caab60 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -212,20 +212,6 @@ declare namespace FourSlashInterface { start: number; end: number; } - export interface TextChange { - span: TextSpan; - newText: string; - } - export interface FileTextChanges { - fileName: string; - textChanges: readonly TextChange[]; - isNewFile?: boolean; - } - export interface MapCodeDocumentMapping { - fileName?: string; - focusLocations?: TextSpan[][]; - contents: string[]; - } class test_ { markers(): Marker[]; markerNames(): string[]; From 7c60bbd3b77257f16bde0fed3737b941038172dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Wed, 22 May 2024 13:46:34 -0700 Subject: [PATCH 10/15] move tests over to taking changes as an array of strings --- src/harness/fourslashImpl.ts | 6 ++--- src/harness/fourslashInterfaceImpl.ts | 4 ++-- .../mapCodeClassInvalidClassMember.mapCode.ts | 1 + ...mapCodeFocusLocationReplacement.mapCode.ts | 1 + .../mapCodeMethodInsertion.mapCode.ts | 1 + .../mapCodeMethodReplacement.mapCode.ts | 1 + .../mapCodeMixedClassDeclaration.mapCode.ts | 1 + .../mapCodeNestedClassIfInsertion.mapCode.ts | 1 + ...mapCodeNestedClassIfReplacement.mapCode.ts | 1 + .../mapCodeNestedForInsertion.mapCode.ts | 1 + .../mapCodeNestedForOfInsertion.mapCode.ts | 1 + .../mapCodeNestedForOfReplacement.mapCode.ts | 1 + .../mapCodeNestedForReplacement.mapCode.ts | 1 + .../mapCodeNestedIfInsertion.mapCode.ts | 1 + .../mapCodeNestedIfReplace.mapCode.ts | 1 + .../mapCodeNestedLabeledInsertion.mapCode.ts | 1 + .../mapCodeNestedLabeledReplace.mapCode.ts | 1 + .../mapCodeNestedWhileInsertion.mapCode.ts | 1 + .../mapCodeNestedWhileReplace.mapCode.ts | 1 + .../mapCodeRangeReplacement.mapCode.ts | 1 + .../mapCodeReplaceUsingRange.mapCode.ts | 1 + .../mapCodeToplevelInsert.mapCode.ts | 1 + .../mapCodeToplevelInsertNoClass.mapCode.ts | 1 + .../mapCodeToplevelReplace.mapCode.ts | 1 + tests/cases/fourslash/fourslash.ts | 2 +- .../mapCodeClassInvalidClassMember.ts | 13 ++++++----- .../mapCodeFocusLocationReplacement.ts | 13 ++++++----- .../cases/fourslash/mapCodeMethodInsertion.ts | 13 ++++++----- .../fourslash/mapCodeMethodReplacement.ts | 13 ++++++----- .../fourslash/mapCodeMixedClassDeclaration.ts | 23 ++++++++++--------- .../mapCodeNestedClassIfInsertion.ts | 13 ++++++----- .../mapCodeNestedClassIfReplacement.ts | 13 ++++++----- .../fourslash/mapCodeNestedForInsertion.ts | 15 ++++++------ .../fourslash/mapCodeNestedForOfInsertion.ts | 15 ++++++------ .../mapCodeNestedForOfReplacement.ts | 15 ++++++------ .../fourslash/mapCodeNestedForReplacement.ts | 15 ++++++------ .../fourslash/mapCodeNestedIfInsertion.ts | 15 ++++++------ .../cases/fourslash/mapCodeNestedIfReplace.ts | 15 ++++++------ .../mapCodeNestedLabeledInsertion.ts | 17 +++++++------- .../fourslash/mapCodeNestedLabeledReplace.ts | 17 +++++++------- .../fourslash/mapCodeNestedWhileInsertion.ts | 15 ++++++------ .../fourslash/mapCodeNestedWhileReplace.ts | 15 ++++++------ .../fourslash/mapCodeRangeReplacement.ts | 21 +++++++++-------- .../fourslash/mapCodeReplaceUsingRange.ts | 13 ++++++----- .../cases/fourslash/mapCodeToplevelInsert.ts | 13 ++++++----- .../fourslash/mapCodeToplevelInsertNoClass.ts | 13 ++++++----- .../cases/fourslash/mapCodeToplevelReplace.ts | 13 ++++++----- 47 files changed, 203 insertions(+), 159 deletions(-) diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 5c7d576a29a4b..5693b986320c5 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -4513,9 +4513,8 @@ export class TestState { public baselineMapCode( ranges: Range[], - changesFilename: string, + changes: string[] = [], ): void { - const changes = this.getFileContent(changesFilename); let fileName: string | undefined; const focusLocations = ranges.map(({ fileName: fn, pos, end }) => { if (!fileName) { @@ -4546,7 +4545,8 @@ export class TestState { } const edits = this.languageService.mapCode( fileName, - [changes], + // We trim the leading whitespace stuff just so our test cases can be more readable. + changes, focusLocations, this.formatCodeSettings, {}, diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index cc101cc148e58..a22854e5a231e 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -240,8 +240,8 @@ export class VerifyNegatable { this.state.uncommentSelection(newFileContent); } - public baselineMapCode(ranges: FourSlash.Range[], changesFilename: string): void { - this.state.baselineMapCode(ranges, changesFilename); + public baselineMapCode(ranges: FourSlash.Range[], changes: string[] = []): void { + this.state.baselineMapCode(ranges, changes); } } diff --git a/tests/baselines/reference/mapCodeClassInvalidClassMember.mapCode.ts b/tests/baselines/reference/mapCodeClassInvalidClassMember.mapCode.ts index 10aaee3330526..973388e10c6b5 100644 --- a/tests/baselines/reference/mapCodeClassInvalidClassMember.mapCode.ts +++ b/tests/baselines/reference/mapCodeClassInvalidClassMember.mapCode.ts @@ -5,6 +5,7 @@ class MyClass {[||] } // === INCOMING CHANGES === + if (false) { return "hello"; } diff --git a/tests/baselines/reference/mapCodeFocusLocationReplacement.mapCode.ts b/tests/baselines/reference/mapCodeFocusLocationReplacement.mapCode.ts index 193db003fc193..ee5321aaeee56 100644 --- a/tests/baselines/reference/mapCodeFocusLocationReplacement.mapCode.ts +++ b/tests/baselines/reference/mapCodeFocusLocationReplacement.mapCode.ts @@ -30,6 +30,7 @@ function baz() { } // === INCOMING CHANGES === + if (x === y) { return x + y; } diff --git a/tests/baselines/reference/mapCodeMethodInsertion.mapCode.ts b/tests/baselines/reference/mapCodeMethodInsertion.mapCode.ts index a370254451a3e..22a5fb16dce66 100644 --- a/tests/baselines/reference/mapCodeMethodInsertion.mapCode.ts +++ b/tests/baselines/reference/mapCodeMethodInsertion.mapCode.ts @@ -15,6 +15,7 @@ class MyClass {[||] } // === INCOMING CHANGES === + quux() { return 4; } diff --git a/tests/baselines/reference/mapCodeMethodReplacement.mapCode.ts b/tests/baselines/reference/mapCodeMethodReplacement.mapCode.ts index 67277b119faa0..fb3468d1c7868 100644 --- a/tests/baselines/reference/mapCodeMethodReplacement.mapCode.ts +++ b/tests/baselines/reference/mapCodeMethodReplacement.mapCode.ts @@ -15,6 +15,7 @@ class MyClass { } // === INCOMING CHANGES === + bar() { return 'hello'; } diff --git a/tests/baselines/reference/mapCodeMixedClassDeclaration.mapCode.ts b/tests/baselines/reference/mapCodeMixedClassDeclaration.mapCode.ts index 796b9b37e8248..c0321464e0a32 100644 --- a/tests/baselines/reference/mapCodeMixedClassDeclaration.mapCode.ts +++ b/tests/baselines/reference/mapCodeMixedClassDeclaration.mapCode.ts @@ -12,6 +12,7 @@ class MyClass {[||] } // === INCOMING CHANGES === + x = 3; bar() { return 'hello'; diff --git a/tests/baselines/reference/mapCodeNestedClassIfInsertion.mapCode.ts b/tests/baselines/reference/mapCodeNestedClassIfInsertion.mapCode.ts index 0dcf31d7a0bc8..09a9e3024fef4 100644 --- a/tests/baselines/reference/mapCodeNestedClassIfInsertion.mapCode.ts +++ b/tests/baselines/reference/mapCodeNestedClassIfInsertion.mapCode.ts @@ -17,6 +17,7 @@ class MyClass { } // === INCOMING CHANGES === + if (false) { return "hello"; } diff --git a/tests/baselines/reference/mapCodeNestedClassIfReplacement.mapCode.ts b/tests/baselines/reference/mapCodeNestedClassIfReplacement.mapCode.ts index 44bf9f2bf944d..e4708e591df81 100644 --- a/tests/baselines/reference/mapCodeNestedClassIfReplacement.mapCode.ts +++ b/tests/baselines/reference/mapCodeNestedClassIfReplacement.mapCode.ts @@ -17,6 +17,7 @@ class MyClass { } // === INCOMING CHANGES === + if (true) { return "hello"; } diff --git a/tests/baselines/reference/mapCodeNestedForInsertion.mapCode.ts b/tests/baselines/reference/mapCodeNestedForInsertion.mapCode.ts index fa175a9a5b314..11076bb631335 100644 --- a/tests/baselines/reference/mapCodeNestedForInsertion.mapCode.ts +++ b/tests/baselines/reference/mapCodeNestedForInsertion.mapCode.ts @@ -12,6 +12,7 @@ function foo() { } // === INCOMING CHANGES === + for (let j = 0; j < 10; j++) { console.log("goodbye"); console.log("world"); diff --git a/tests/baselines/reference/mapCodeNestedForOfInsertion.mapCode.ts b/tests/baselines/reference/mapCodeNestedForOfInsertion.mapCode.ts index e71d23085d6c0..19673ad8160ff 100644 --- a/tests/baselines/reference/mapCodeNestedForOfInsertion.mapCode.ts +++ b/tests/baselines/reference/mapCodeNestedForOfInsertion.mapCode.ts @@ -10,6 +10,7 @@ function foo() { } // === INCOMING CHANGES === + for (const y of [1, 2, 3]) { console.log("goodbye"); console.log("world"); diff --git a/tests/baselines/reference/mapCodeNestedForOfReplacement.mapCode.ts b/tests/baselines/reference/mapCodeNestedForOfReplacement.mapCode.ts index 1ba34b4ffdabe..c0f25917e2592 100644 --- a/tests/baselines/reference/mapCodeNestedForOfReplacement.mapCode.ts +++ b/tests/baselines/reference/mapCodeNestedForOfReplacement.mapCode.ts @@ -10,6 +10,7 @@ function foo() { } // === INCOMING CHANGES === + for (const x of [1, 2, 3]) { console.log("goodbye"); console.log("world"); diff --git a/tests/baselines/reference/mapCodeNestedForReplacement.mapCode.ts b/tests/baselines/reference/mapCodeNestedForReplacement.mapCode.ts index 1194d4f6d207c..d0ed70bd659d3 100644 --- a/tests/baselines/reference/mapCodeNestedForReplacement.mapCode.ts +++ b/tests/baselines/reference/mapCodeNestedForReplacement.mapCode.ts @@ -10,6 +10,7 @@ function foo() { } // === INCOMING CHANGES === + for (let x = 0; x < 10; x++) { console.log("goodbye"); console.log("world"); diff --git a/tests/baselines/reference/mapCodeNestedIfInsertion.mapCode.ts b/tests/baselines/reference/mapCodeNestedIfInsertion.mapCode.ts index 2b82da88c7faa..2d9a00c10a465 100644 --- a/tests/baselines/reference/mapCodeNestedIfInsertion.mapCode.ts +++ b/tests/baselines/reference/mapCodeNestedIfInsertion.mapCode.ts @@ -12,6 +12,7 @@ function foo() { } // === INCOMING CHANGES === + if (y === x) { console.log("goodbye"); console.log("world"); diff --git a/tests/baselines/reference/mapCodeNestedIfReplace.mapCode.ts b/tests/baselines/reference/mapCodeNestedIfReplace.mapCode.ts index e3042ffe9c751..5e999ee8b1c6f 100644 --- a/tests/baselines/reference/mapCodeNestedIfReplace.mapCode.ts +++ b/tests/baselines/reference/mapCodeNestedIfReplace.mapCode.ts @@ -12,6 +12,7 @@ function foo() { } // === INCOMING CHANGES === + if (x === y) { console.log("goodbye"); console.log("world"); diff --git a/tests/baselines/reference/mapCodeNestedLabeledInsertion.mapCode.ts b/tests/baselines/reference/mapCodeNestedLabeledInsertion.mapCode.ts index 24f89c88646d4..f4e6f1806776f 100644 --- a/tests/baselines/reference/mapCodeNestedLabeledInsertion.mapCode.ts +++ b/tests/baselines/reference/mapCodeNestedLabeledInsertion.mapCode.ts @@ -13,6 +13,7 @@ function foo() { } // === INCOMING CHANGES === + otherLabel: if (y === x) { console.log("goodbye"); console.log("world"); diff --git a/tests/baselines/reference/mapCodeNestedLabeledReplace.mapCode.ts b/tests/baselines/reference/mapCodeNestedLabeledReplace.mapCode.ts index 114ce09b8d4c9..e1f3f34d52060 100644 --- a/tests/baselines/reference/mapCodeNestedLabeledReplace.mapCode.ts +++ b/tests/baselines/reference/mapCodeNestedLabeledReplace.mapCode.ts @@ -13,6 +13,7 @@ function foo() { } // === INCOMING CHANGES === + myLabel: if (y === x) { console.log("goodbye"); console.log("world"); diff --git a/tests/baselines/reference/mapCodeNestedWhileInsertion.mapCode.ts b/tests/baselines/reference/mapCodeNestedWhileInsertion.mapCode.ts index 2e6862eadf816..b16b14907addb 100644 --- a/tests/baselines/reference/mapCodeNestedWhileInsertion.mapCode.ts +++ b/tests/baselines/reference/mapCodeNestedWhileInsertion.mapCode.ts @@ -12,6 +12,7 @@ function foo() { } // === INCOMING CHANGES === + while (y === x) { console.log("goodbye"); console.log("world"); diff --git a/tests/baselines/reference/mapCodeNestedWhileReplace.mapCode.ts b/tests/baselines/reference/mapCodeNestedWhileReplace.mapCode.ts index d93bdc1e9e23a..f9a7182b543a3 100644 --- a/tests/baselines/reference/mapCodeNestedWhileReplace.mapCode.ts +++ b/tests/baselines/reference/mapCodeNestedWhileReplace.mapCode.ts @@ -12,6 +12,7 @@ function foo() { } // === INCOMING CHANGES === + while (x === y) { console.log("goodbye"); console.log("world"); diff --git a/tests/baselines/reference/mapCodeRangeReplacement.mapCode.ts b/tests/baselines/reference/mapCodeRangeReplacement.mapCode.ts index 3d4eb3715f918..8d986a0607c2c 100644 --- a/tests/baselines/reference/mapCodeRangeReplacement.mapCode.ts +++ b/tests/baselines/reference/mapCodeRangeReplacement.mapCode.ts @@ -20,6 +20,7 @@ while (false) { } // === INCOMING CHANGES === + if (foo == bar) { console.log("huh"); } diff --git a/tests/baselines/reference/mapCodeReplaceUsingRange.mapCode.ts b/tests/baselines/reference/mapCodeReplaceUsingRange.mapCode.ts index 7afc919ae8aca..147e8bf542464 100644 --- a/tests/baselines/reference/mapCodeReplaceUsingRange.mapCode.ts +++ b/tests/baselines/reference/mapCodeReplaceUsingRange.mapCode.ts @@ -9,6 +9,7 @@ function bar() { }|] // === INCOMING CHANGES === + function foo() { return 3; } diff --git a/tests/baselines/reference/mapCodeToplevelInsert.mapCode.ts b/tests/baselines/reference/mapCodeToplevelInsert.mapCode.ts index d0f943c45867a..0cbd78d94f91e 100644 --- a/tests/baselines/reference/mapCodeToplevelInsert.mapCode.ts +++ b/tests/baselines/reference/mapCodeToplevelInsert.mapCode.ts @@ -8,6 +8,7 @@ function bar() { return 2; } // === INCOMING CHANGES === + function baz() { return 3; } diff --git a/tests/baselines/reference/mapCodeToplevelInsertNoClass.mapCode.ts b/tests/baselines/reference/mapCodeToplevelInsertNoClass.mapCode.ts index 87ea9145a0716..54efddff0e38d 100644 --- a/tests/baselines/reference/mapCodeToplevelInsertNoClass.mapCode.ts +++ b/tests/baselines/reference/mapCodeToplevelInsertNoClass.mapCode.ts @@ -8,6 +8,7 @@ function bar() { return 2; } // === INCOMING CHANGES === + baz() { return 3; } diff --git a/tests/baselines/reference/mapCodeToplevelReplace.mapCode.ts b/tests/baselines/reference/mapCodeToplevelReplace.mapCode.ts index 4e4f6b42e89b0..effe07ad6a785 100644 --- a/tests/baselines/reference/mapCodeToplevelReplace.mapCode.ts +++ b/tests/baselines/reference/mapCodeToplevelReplace.mapCode.ts @@ -9,6 +9,7 @@ function bar() { } // === INCOMING CHANGES === + function foo() { return 3; } diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 4eff8b9caab60..52b04389b280b 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -452,7 +452,7 @@ declare namespace FourSlashInterface { copiedFrom?: { file: string, range: { pos: number, end: number }[] }; } }): void; - baselineMapCode(ranges: Range[], changesFilename?: string): void; + baselineMapCode(ranges: Range[], changes: string[]): void; } class edit { caretPosition(): Marker; diff --git a/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts b/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts index 0ff05e37b3393..3d691bdfe3244 100644 --- a/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts +++ b/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts @@ -1,13 +1,14 @@ /// -// @Filename: /incomingChanges.ts -//// if (false) { -//// return "hello"; -//// } -//// // @Filename: /index.ts //// class MyClass {[||] //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +if (false) { + return "hello"; +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts b/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts index 1c01f6065ab25..e254e4b7ffefb 100644 --- a/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts +++ b/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts @@ -1,10 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// if (x === y) { -//// return x + y; -//// } -//// // @Filename: /index.ts //// function foo() { //// const x: number = 1; @@ -35,4 +30,10 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +if (x === y) { + return x + y; +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeMethodInsertion.ts b/tests/cases/fourslash/mapCodeMethodInsertion.ts index 3f966f7ef7e6d..552eb0a7e9875 100644 --- a/tests/cases/fourslash/mapCodeMethodInsertion.ts +++ b/tests/cases/fourslash/mapCodeMethodInsertion.ts @@ -1,10 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// quux() { -//// return 4; -//// } -//// // @Filename: /index.ts //// class MyClass {[||] //// x = 1; @@ -20,4 +15,10 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +quux() { + return 4; +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeMethodReplacement.ts b/tests/cases/fourslash/mapCodeMethodReplacement.ts index 2787d50af95ff..665d005da0e83 100644 --- a/tests/cases/fourslash/mapCodeMethodReplacement.ts +++ b/tests/cases/fourslash/mapCodeMethodReplacement.ts @@ -1,10 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// bar() { -//// return 'hello'; -//// } -//// // @Filename: /index.ts //// class MyClass { //// x = 1; @@ -20,4 +15,10 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); +verify.baselineMapCode(test.ranges(), [ +` +bar() { + return 'hello'; +} +` +]); diff --git a/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts b/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts index 1b3d306637c52..06c3455b18ac9 100644 --- a/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts +++ b/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts @@ -1,15 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// x = 3; -//// bar() { -//// return 'hello'; -//// } -//// baz() { -//// return 3; -//// } -//// y = 2; -//// // @Filename: /index.ts //// class MyClass {[||] //// x = 1; @@ -22,4 +12,15 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +x = 3; +bar() { + return 'hello'; +} +baz() { + return 3; +} +y = 2; +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts b/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts index 8f609e16267d0..c45724806eaa9 100644 --- a/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts @@ -1,10 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// if (false) { -//// return "hello"; -//// } -//// // @Filename: /index.ts //// class MyClass { //// x = 1; @@ -22,4 +17,10 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +if (false) { + return "hello"; +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts b/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts index d944d05fa3f16..1304fff19e2fb 100644 --- a/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts +++ b/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts @@ -1,10 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// if (true) { -//// return "hello"; -//// } -//// // @Filename: /index.ts //// class MyClass { //// x = 1; @@ -22,4 +17,10 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +if (true) { + return "hello"; +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForInsertion.ts b/tests/cases/fourslash/mapCodeNestedForInsertion.ts index 09ead4ee37389..d43729b62c2be 100644 --- a/tests/cases/fourslash/mapCodeNestedForInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedForInsertion.ts @@ -1,11 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// for (let j = 0; j < 10; j++) { -//// console.log("goodbye"); -//// console.log("world"); -//// } -//// // @Filename: /index.ts //// function foo() { //// const x: number = 1; @@ -18,4 +12,11 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +for (let j = 0; j < 10; j++) { + console.log("goodbye"); + console.log("world"); +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts b/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts index 4a37e87ec5eab..66a66a1c85261 100644 --- a/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts @@ -1,11 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// for (const y of [1, 2, 3]) { -//// console.log("goodbye"); -//// console.log("world"); -//// } -//// // @Filename: /index.ts //// function foo() { //// for (const x of [1, 2, 3])[||] { @@ -16,4 +10,11 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +for (const y of [1, 2, 3]) { + console.log("goodbye"); + console.log("world"); +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts b/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts index 32c6414c2f01e..7b656eedef52b 100644 --- a/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts +++ b/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts @@ -1,11 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// for (const x of [1, 2, 3]) { -//// console.log("goodbye"); -//// console.log("world"); -//// } -//// // @Filename: /index.ts //// function foo() { //// for (const x of [1, 2, 3]) [||]{ @@ -16,4 +10,11 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +for (const x of [1, 2, 3]) { + console.log("goodbye"); + console.log("world"); +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedForReplacement.ts b/tests/cases/fourslash/mapCodeNestedForReplacement.ts index ced6e5264f425..d4ee1b71656dd 100644 --- a/tests/cases/fourslash/mapCodeNestedForReplacement.ts +++ b/tests/cases/fourslash/mapCodeNestedForReplacement.ts @@ -1,11 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// for (let x = 0; x < 10; x++) { -//// console.log("goodbye"); -//// console.log("world"); -//// } -//// // @Filename: /index.ts //// function foo() { //// for (let x = 0; x < 10; x++) [||]{ @@ -16,4 +10,11 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +for (let x = 0; x < 10; x++) { + console.log("goodbye"); + console.log("world"); +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedIfInsertion.ts b/tests/cases/fourslash/mapCodeNestedIfInsertion.ts index 1732172c2302e..750542ef9887a 100644 --- a/tests/cases/fourslash/mapCodeNestedIfInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedIfInsertion.ts @@ -1,11 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// if (y === x) { -//// console.log("goodbye"); -//// console.log("world"); -//// } -//// // @Filename: /index.ts //// function foo() { //// const x: number = 1; @@ -18,4 +12,11 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +if (y === x) { + console.log("goodbye"); + console.log("world"); +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedIfReplace.ts b/tests/cases/fourslash/mapCodeNestedIfReplace.ts index c3ca1c5fb8366..fb56c79d2b69d 100644 --- a/tests/cases/fourslash/mapCodeNestedIfReplace.ts +++ b/tests/cases/fourslash/mapCodeNestedIfReplace.ts @@ -1,11 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// if (x === y) { -//// console.log("goodbye"); -//// console.log("world"); -//// } -//// // @Filename: /index.ts //// function foo() { //// const x: number = 1; @@ -18,4 +12,11 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +if (x === y) { + console.log("goodbye"); + console.log("world"); +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts b/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts index fc4a87471da41..ff0ef4bae5964 100644 --- a/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts @@ -1,12 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// otherLabel: if (y === x) { -//// console.log("goodbye"); -//// console.log("world"); -//// break otherLabel; -//// } -//// // @Filename: /index.ts //// function foo() { //// const x: number = 1; @@ -20,4 +13,12 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +otherLabel: if (y === x) { + console.log("goodbye"); + console.log("world"); + break otherLabel; +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts b/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts index 0e60d329af91a..fcda6d1a3c378 100644 --- a/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts +++ b/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts @@ -1,12 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// myLabel: if (y === x) { -//// console.log("goodbye"); -//// console.log("world"); -//// break myLabel; -//// } -//// // @Filename: /index.ts //// function foo() { //// const x: number = 1; @@ -20,4 +13,12 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +myLabel: if (y === x) { + console.log("goodbye"); + console.log("world"); + break myLabel; +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts b/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts index ac98cd69c0f50..9bffa41cf965a 100644 --- a/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts @@ -1,11 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// while (y === x) { -//// console.log("goodbye"); -//// console.log("world"); -//// } -//// // @Filename: /index.ts //// function foo() { //// const x: number = 1; @@ -18,4 +12,11 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +while (y === x) { + console.log("goodbye"); + console.log("world"); +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeNestedWhileReplace.ts b/tests/cases/fourslash/mapCodeNestedWhileReplace.ts index 7bd21a9698e18..093d0e9902cb8 100644 --- a/tests/cases/fourslash/mapCodeNestedWhileReplace.ts +++ b/tests/cases/fourslash/mapCodeNestedWhileReplace.ts @@ -1,11 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// while (x === y) { -//// console.log("goodbye"); -//// console.log("world"); -//// } -//// // @Filename: /index.ts //// function foo() { //// const x: number = 1; @@ -18,4 +12,11 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +while (x === y) { + console.log("goodbye"); + console.log("world"); +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeRangeReplacement.ts b/tests/cases/fourslash/mapCodeRangeReplacement.ts index 8fddddb6e918e..fed9312f92f89 100644 --- a/tests/cases/fourslash/mapCodeRangeReplacement.ts +++ b/tests/cases/fourslash/mapCodeRangeReplacement.ts @@ -1,14 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// if (foo == bar) { -//// console.log("huh"); -//// } -//// -//// function baz() { -//// return 'baz'; -//// } -//// // @Filename: /index.ts //// function foo() { //// return 1; @@ -29,4 +20,14 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +if (foo == bar) { + console.log("huh"); +} + +function baz() { + return 'baz'; +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeReplaceUsingRange.ts b/tests/cases/fourslash/mapCodeReplaceUsingRange.ts index fb723acc7c835..1c13827ac4713 100644 --- a/tests/cases/fourslash/mapCodeReplaceUsingRange.ts +++ b/tests/cases/fourslash/mapCodeReplaceUsingRange.ts @@ -1,10 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// function foo() { -//// return 3; -//// } -//// // @Filename: /index.ts //// [|function foo() { //// return 1; @@ -14,4 +9,10 @@ //// }|] //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); +verify.baselineMapCode(test.ranges(), [ +` +function foo() { + return 3; +} +` +]); diff --git a/tests/cases/fourslash/mapCodeToplevelInsert.ts b/tests/cases/fourslash/mapCodeToplevelInsert.ts index 8b0f7b2c431a8..b82aec34b242b 100644 --- a/tests/cases/fourslash/mapCodeToplevelInsert.ts +++ b/tests/cases/fourslash/mapCodeToplevelInsert.ts @@ -1,10 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// function baz() { -//// return 3; -//// } -//// // @Filename: /index.ts //// function foo() { //// return 1; @@ -13,4 +8,10 @@ //// return 2; //// } -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +function baz() { + return 3; +} +` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts b/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts index 9feb70fb13f04..2078f12c9a30d 100644 --- a/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts +++ b/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts @@ -1,10 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// baz() { -//// return 3; -//// } -//// // @Filename: /index.ts //// function foo() { //// return 1; @@ -13,4 +8,10 @@ //// return 2; //// } -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); +verify.baselineMapCode(test.ranges(), [ +` +baz() { + return 3; +} +` +]); diff --git a/tests/cases/fourslash/mapCodeToplevelReplace.ts b/tests/cases/fourslash/mapCodeToplevelReplace.ts index dc11d2d702e38..bb763e0407a32 100644 --- a/tests/cases/fourslash/mapCodeToplevelReplace.ts +++ b/tests/cases/fourslash/mapCodeToplevelReplace.ts @@ -1,10 +1,5 @@ /// -// @Filename: /incomingChanges.ts -//// function foo() { -//// return 3; -//// } -//// // @Filename: /index.ts //// function foo() { //// return 1; @@ -14,4 +9,10 @@ //// } //// -verify.baselineMapCode(test.ranges(), "/incomingChanges.ts"); \ No newline at end of file +verify.baselineMapCode(test.ranges(), [ +` +function foo() { + return 3; +} +` +]); \ No newline at end of file From e7dc55fb65c299233b95723ff530eb7d0172c822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Wed, 22 May 2024 14:08:10 -0700 Subject: [PATCH 11/15] add tests for different focusLocation/changes scenario combinations --- src/harness/fourslashImpl.ts | 12 ++--- src/services/mapCode.ts | 1 - ...mapCodeMultipleChangesAndRanges.mapCode.ts | 52 +++++++++++++++++++ .../reference/mapCodeNoChanges.mapCode.ts | 27 ++++++++++ .../reference/mapCodeNoRanges.mapCode.ts | 27 ++++++++++ .../mapCodeMultipleChangesAndRanges.ts | 37 +++++++++++++ tests/cases/fourslash/mapCodeNoChanges.ts | 16 ++++++ tests/cases/fourslash/mapCodeNoRanges.ts | 19 +++++++ 8 files changed, 181 insertions(+), 10 deletions(-) create mode 100644 tests/baselines/reference/mapCodeMultipleChangesAndRanges.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNoChanges.mapCode.ts create mode 100644 tests/baselines/reference/mapCodeNoRanges.mapCode.ts create mode 100644 tests/cases/fourslash/mapCodeMultipleChangesAndRanges.ts create mode 100644 tests/cases/fourslash/mapCodeNoChanges.ts create mode 100644 tests/cases/fourslash/mapCodeNoRanges.ts diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 5693b986320c5..9ea2a61e035c1 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -4515,16 +4515,10 @@ export class TestState { ranges: Range[], changes: string[] = [], ): void { - let fileName: string | undefined; - const focusLocations = ranges.map(({ fileName: fn, pos, end }) => { - if (!fileName) { - fileName = fn; - } + const fileName = this.activeFile.fileName; + const focusLocations = ranges.map(({ pos, end }) => { return [{ start: pos, length: end - pos }]; }); - if (!fileName) { - throw new Error("No ranges passed in, or something went wrong."); - } let before = this.getFileContent(fileName); focusLocations.sort((a, b) => a[0].start - b[0].start); for (const subLoc of focusLocations) { @@ -4557,7 +4551,7 @@ export class TestState { // === ORIGINAL === ${before} // === INCOMING CHANGES === -${changes} +${changes.join("\n// ---\n")} // === MAPPED === ${after}`; this.baseline("mapCode", baseline, ".mapCode.ts"); diff --git a/src/services/mapCode.ts b/src/services/mapCode.ts index 68c8754914209..db5c9779d88e1 100644 --- a/src/services/mapCode.ts +++ b/src/services/mapCode.ts @@ -3,7 +3,6 @@ import { ClassElement, ClassLikeDeclaration, createSourceFile, - emptyArray, FileTextChanges, find, findAncestor, diff --git a/tests/baselines/reference/mapCodeMultipleChangesAndRanges.mapCode.ts b/tests/baselines/reference/mapCodeMultipleChangesAndRanges.mapCode.ts new file mode 100644 index 0000000000000..1105222b7595b --- /dev/null +++ b/tests/baselines/reference/mapCodeMultipleChangesAndRanges.mapCode.ts @@ -0,0 +1,52 @@ +// === mapCode === + +// === ORIGINAL === + +[|function foo() { + const x: number = 1; + const y: number = 2; + if (x === y) [||]{ + console.log("hello"); + console.log("you"); + } + return 1; +}|] + +function bar() { + [|return 2|]; +} + +// === INCOMING CHANGES === + +if (x === y) { + console.log("goodbye"); + console.log("world"); +} + +// --- + +function bar() { + return 3; +} + +// --- + +method() { + return 'nope'; +} + +// === MAPPED === + +function foo() { + const x: number = 1; + const y: number = 2; + if (x === y) { + console.log("goodbye"); + console.log("world"); + } + return 1; +} + +function bar() { + return 3; +} diff --git a/tests/baselines/reference/mapCodeNoChanges.mapCode.ts b/tests/baselines/reference/mapCodeNoChanges.mapCode.ts new file mode 100644 index 0000000000000..fc7b528959574 --- /dev/null +++ b/tests/baselines/reference/mapCodeNoChanges.mapCode.ts @@ -0,0 +1,27 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + return 1; +} +[||] +function bar() { + return 2; +} +function baz() { + return 3; +} + +// === INCOMING CHANGES === + +// === MAPPED === +function foo() { + return 1; +} + +function bar() { + return 2; +} +function baz() { + return 3; +} diff --git a/tests/baselines/reference/mapCodeNoRanges.mapCode.ts b/tests/baselines/reference/mapCodeNoRanges.mapCode.ts new file mode 100644 index 0000000000000..17553ff569f3d --- /dev/null +++ b/tests/baselines/reference/mapCodeNoRanges.mapCode.ts @@ -0,0 +1,27 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + return 1; +} +function bar() { + return 2; +} + +// === INCOMING CHANGES === + +function baz() { + return 3; +} + +// === MAPPED === +function foo() { + return 1; +} +function bar() { + return 2; +} + +function baz() { + return 3; +} diff --git a/tests/cases/fourslash/mapCodeMultipleChangesAndRanges.ts b/tests/cases/fourslash/mapCodeMultipleChangesAndRanges.ts new file mode 100644 index 0000000000000..c8f8a0038b5c9 --- /dev/null +++ b/tests/cases/fourslash/mapCodeMultipleChangesAndRanges.ts @@ -0,0 +1,37 @@ +/// + +// @Filename: /index.ts +//// +//// [|function foo() { +//// const x: number = 1; +//// const y: number = 2; +//// if (x === y) [||]{ +//// console.log("hello"); +//// console.log("you"); +//// } +//// return 1; +//// }|] +//// +//// function bar() { +//// [|return 2|]; +//// } +//// + +verify.baselineMapCode(test.ranges(), [ +` +if (x === y) { + console.log("goodbye"); + console.log("world"); +} +`, +` +function bar() { + return 3; +} +`, +` +method() { + return 'nope'; +} +` +]); diff --git a/tests/cases/fourslash/mapCodeNoChanges.ts b/tests/cases/fourslash/mapCodeNoChanges.ts new file mode 100644 index 0000000000000..8639add6f9a0d --- /dev/null +++ b/tests/cases/fourslash/mapCodeNoChanges.ts @@ -0,0 +1,16 @@ +/// + +// @Filename: /index.ts +//// function foo() { +//// return 1; +//// } +//// [||] +//// function bar() { +//// return 2; +//// } +//// function baz() { +//// return 3; +//// } +//// + +verify.baselineMapCode(test.ranges(), []); diff --git a/tests/cases/fourslash/mapCodeNoRanges.ts b/tests/cases/fourslash/mapCodeNoRanges.ts new file mode 100644 index 0000000000000..8a2fa947f0d24 --- /dev/null +++ b/tests/cases/fourslash/mapCodeNoRanges.ts @@ -0,0 +1,19 @@ +/// + +// @Filename: /index.ts +//// function foo() { +//// return 1; +//// } +//// function bar() { +//// return 2; +//// } +//// + +verify.baselineMapCode([], [ +` +function baz() { + return 3; +} +` +]); + From 4da7331a539d4db6bc2d9598a0634f30c9689000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Wed, 22 May 2024 14:12:19 -0700 Subject: [PATCH 12/15] sort focusLocations only after calling the API --- src/harness/fourslashImpl.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 9ea2a61e035c1..a03c962d4ceb2 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -4520,6 +4520,15 @@ export class TestState { return [{ start: pos, length: end - pos }]; }); let before = this.getFileContent(fileName); + const edits = this.languageService.mapCode( + fileName, + // We trim the leading whitespace stuff just so our test cases can be more readable. + changes, + focusLocations, + this.formatCodeSettings, + {}, + ); + this.applyChanges(edits); focusLocations.sort((a, b) => a[0].start - b[0].start); for (const subLoc of focusLocations) { for (const { start, length } of subLoc) { @@ -4537,15 +4546,6 @@ export class TestState { before = before.slice(0, start + offset) + "[|" + before.slice(start + offset, start + offset + length) + "|]" + before.slice(start + offset + length); } } - const edits = this.languageService.mapCode( - fileName, - // We trim the leading whitespace stuff just so our test cases can be more readable. - changes, - focusLocations, - this.formatCodeSettings, - {}, - ); - this.applyChanges(edits); const after = this.getFileContent(fileName); const baseline = ` // === ORIGINAL === From db9d1e933100aabf07a7d968ee7cdbaacc684635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Wed, 22 May 2024 15:03:41 -0700 Subject: [PATCH 13/15] Range[][] and such changes --- src/harness/fourslashImpl.ts | 13 +++++++++---- src/harness/fourslashInterfaceImpl.ts | 2 +- src/services/mapCode.ts | 10 ++++++---- tests/cases/fourslash/fourslash.ts | 2 +- .../fourslash/mapCodeClassInvalidClassMember.ts | 2 +- .../fourslash/mapCodeFocusLocationReplacement.ts | 2 +- tests/cases/fourslash/mapCodeMethodInsertion.ts | 2 +- tests/cases/fourslash/mapCodeMethodReplacement.ts | 2 +- .../cases/fourslash/mapCodeMixedClassDeclaration.ts | 2 +- .../fourslash/mapCodeMultipleChangesAndRanges.ts | 3 ++- .../fourslash/mapCodeNestedClassIfInsertion.ts | 2 +- .../fourslash/mapCodeNestedClassIfReplacement.ts | 2 +- tests/cases/fourslash/mapCodeNestedForInsertion.ts | 2 +- .../cases/fourslash/mapCodeNestedForOfInsertion.ts | 2 +- .../fourslash/mapCodeNestedForOfReplacement.ts | 2 +- .../cases/fourslash/mapCodeNestedForReplacement.ts | 2 +- tests/cases/fourslash/mapCodeNestedIfInsertion.ts | 2 +- tests/cases/fourslash/mapCodeNestedIfReplace.ts | 2 +- .../fourslash/mapCodeNestedLabeledInsertion.ts | 2 +- .../cases/fourslash/mapCodeNestedLabeledReplace.ts | 2 +- .../cases/fourslash/mapCodeNestedWhileInsertion.ts | 2 +- tests/cases/fourslash/mapCodeNestedWhileReplace.ts | 2 +- tests/cases/fourslash/mapCodeNoChanges.ts | 2 +- tests/cases/fourslash/mapCodeNoRanges.ts | 2 +- tests/cases/fourslash/mapCodeRangeReplacement.ts | 2 +- tests/cases/fourslash/mapCodeReplaceUsingRange.ts | 2 +- tests/cases/fourslash/mapCodeToplevelInsert.ts | 4 ++-- .../cases/fourslash/mapCodeToplevelInsertNoClass.ts | 2 +- tests/cases/fourslash/mapCodeToplevelReplace.ts | 4 ++-- 29 files changed, 45 insertions(+), 37 deletions(-) diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index a03c962d4ceb2..6037d20ce1355 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -4512,13 +4512,15 @@ export class TestState { } public baselineMapCode( - ranges: Range[], + ranges: Range[][], changes: string[] = [], ): void { const fileName = this.activeFile.fileName; - const focusLocations = ranges.map(({ pos, end }) => { - return [{ start: pos, length: end - pos }]; - }); + const focusLocations = ranges.map(r => + r.map(({ pos, end }) => { + return { start: pos, length: end - pos }; + }) + ); let before = this.getFileContent(fileName); const edits = this.languageService.mapCode( fileName, @@ -4529,6 +4531,9 @@ export class TestState { {}, ); this.applyChanges(edits); + focusLocations.forEach(r => { + r.sort((a, b) => a.start - b.start); + }) focusLocations.sort((a, b) => a[0].start - b[0].start); for (const subLoc of focusLocations) { for (const { start, length } of subLoc) { diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index a22854e5a231e..f04ac4594f918 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -240,7 +240,7 @@ export class VerifyNegatable { this.state.uncommentSelection(newFileContent); } - public baselineMapCode(ranges: FourSlash.Range[], changes: string[] = []): void { + public baselineMapCode(ranges: FourSlash.Range[][], changes: string[] = []): void { this.state.baselineMapCode(ranges, changes); } } diff --git a/src/services/mapCode.ts b/src/services/mapCode.ts index db5c9779d88e1..7ffe68d8eacd1 100644 --- a/src/services/mapCode.ts +++ b/src/services/mapCode.ts @@ -52,7 +52,7 @@ export function mapCode( return textChanges.ChangeTracker.with( { host, formatContext, preferences }, changeTracker => { - const parsed = contents.map(parse); + const parsed = contents.map(c => parse(sourceFile, c)); const flattenedLocations = focusLocations && flatten(focusLocations); for (const nodes of parsed) { placeNodeGroup( @@ -70,7 +70,7 @@ export function mapCode( * Tries to parse something into either "top-level" statements, or into blocks * of class-context definitions. */ -function parse(content: string): NodeArray { +function parse(sourceFile: SourceFile, content: string): NodeArray { // We're going to speculatively parse different kinds of contexts to see // which one makes the most sense, and grab the NodeArray from there. Do // this as lazily as possible. @@ -80,8 +80,9 @@ function parse(content: string): NodeArray { createSourceFile( "__mapcode_content_nodes.ts", content, - ScriptTarget.Latest, + sourceFile.languageVersion, /*setParentNodes*/ true, + sourceFile.scriptKind, ), body: (sf: SourceFile) => sf.statements, }, @@ -90,8 +91,9 @@ function parse(content: string): NodeArray { createSourceFile( "__mapcode_class_content_nodes.ts", `class __class {\n${content}\n}`, - ScriptTarget.Latest, + sourceFile.languageVersion, /*setParentNodes*/ true, + sourceFile.scriptKind, ), body: (cw: SourceFile) => (cw.statements[0] as ClassLikeDeclaration).members, }, diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 52b04389b280b..47076727a832e 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -452,7 +452,7 @@ declare namespace FourSlashInterface { copiedFrom?: { file: string, range: { pos: number, end: number }[] }; } }): void; - baselineMapCode(ranges: Range[], changes: string[]): void; + baselineMapCode(ranges: Range[][], changes: string[]): void; } class edit { caretPosition(): Marker; diff --git a/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts b/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts index 3d691bdfe3244..445e16875250e 100644 --- a/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts +++ b/tests/cases/fourslash/mapCodeClassInvalidClassMember.ts @@ -5,7 +5,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` if (false) { return "hello"; diff --git a/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts b/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts index e254e4b7ffefb..99cb8ea19965b 100644 --- a/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts +++ b/tests/cases/fourslash/mapCodeFocusLocationReplacement.ts @@ -30,7 +30,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` if (x === y) { return x + y; diff --git a/tests/cases/fourslash/mapCodeMethodInsertion.ts b/tests/cases/fourslash/mapCodeMethodInsertion.ts index 552eb0a7e9875..a7e09796e0b3a 100644 --- a/tests/cases/fourslash/mapCodeMethodInsertion.ts +++ b/tests/cases/fourslash/mapCodeMethodInsertion.ts @@ -15,7 +15,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` quux() { return 4; diff --git a/tests/cases/fourslash/mapCodeMethodReplacement.ts b/tests/cases/fourslash/mapCodeMethodReplacement.ts index 665d005da0e83..b02fd9e536958 100644 --- a/tests/cases/fourslash/mapCodeMethodReplacement.ts +++ b/tests/cases/fourslash/mapCodeMethodReplacement.ts @@ -15,7 +15,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` bar() { return 'hello'; diff --git a/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts b/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts index 06c3455b18ac9..12482c30abd2f 100644 --- a/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts +++ b/tests/cases/fourslash/mapCodeMixedClassDeclaration.ts @@ -12,7 +12,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` x = 3; bar() { diff --git a/tests/cases/fourslash/mapCodeMultipleChangesAndRanges.ts b/tests/cases/fourslash/mapCodeMultipleChangesAndRanges.ts index c8f8a0038b5c9..172c95245f8ea 100644 --- a/tests/cases/fourslash/mapCodeMultipleChangesAndRanges.ts +++ b/tests/cases/fourslash/mapCodeMultipleChangesAndRanges.ts @@ -17,7 +17,8 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +const [r0, r1, r2] = test.ranges(); +verify.baselineMapCode([[r0], [r2, r1]], [ ` if (x === y) { console.log("goodbye"); diff --git a/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts b/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts index c45724806eaa9..306e1ee3ec562 100644 --- a/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedClassIfInsertion.ts @@ -17,7 +17,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` if (false) { return "hello"; diff --git a/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts b/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts index 1304fff19e2fb..2fe96d62d77e5 100644 --- a/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts +++ b/tests/cases/fourslash/mapCodeNestedClassIfReplacement.ts @@ -17,7 +17,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` if (true) { return "hello"; diff --git a/tests/cases/fourslash/mapCodeNestedForInsertion.ts b/tests/cases/fourslash/mapCodeNestedForInsertion.ts index d43729b62c2be..d07fb264872c0 100644 --- a/tests/cases/fourslash/mapCodeNestedForInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedForInsertion.ts @@ -12,7 +12,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` for (let j = 0; j < 10; j++) { console.log("goodbye"); diff --git a/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts b/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts index 66a66a1c85261..fee6df989d085 100644 --- a/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedForOfInsertion.ts @@ -10,7 +10,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` for (const y of [1, 2, 3]) { console.log("goodbye"); diff --git a/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts b/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts index 7b656eedef52b..9924d87843048 100644 --- a/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts +++ b/tests/cases/fourslash/mapCodeNestedForOfReplacement.ts @@ -10,7 +10,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` for (const x of [1, 2, 3]) { console.log("goodbye"); diff --git a/tests/cases/fourslash/mapCodeNestedForReplacement.ts b/tests/cases/fourslash/mapCodeNestedForReplacement.ts index d4ee1b71656dd..0ba2a25a34d7c 100644 --- a/tests/cases/fourslash/mapCodeNestedForReplacement.ts +++ b/tests/cases/fourslash/mapCodeNestedForReplacement.ts @@ -10,7 +10,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` for (let x = 0; x < 10; x++) { console.log("goodbye"); diff --git a/tests/cases/fourslash/mapCodeNestedIfInsertion.ts b/tests/cases/fourslash/mapCodeNestedIfInsertion.ts index 750542ef9887a..831582391eb6f 100644 --- a/tests/cases/fourslash/mapCodeNestedIfInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedIfInsertion.ts @@ -12,7 +12,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` if (y === x) { console.log("goodbye"); diff --git a/tests/cases/fourslash/mapCodeNestedIfReplace.ts b/tests/cases/fourslash/mapCodeNestedIfReplace.ts index fb56c79d2b69d..3813c7b558a32 100644 --- a/tests/cases/fourslash/mapCodeNestedIfReplace.ts +++ b/tests/cases/fourslash/mapCodeNestedIfReplace.ts @@ -12,7 +12,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` if (x === y) { console.log("goodbye"); diff --git a/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts b/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts index ff0ef4bae5964..5c575e177be7c 100644 --- a/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedLabeledInsertion.ts @@ -13,7 +13,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` otherLabel: if (y === x) { console.log("goodbye"); diff --git a/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts b/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts index fcda6d1a3c378..b4ac9feccc664 100644 --- a/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts +++ b/tests/cases/fourslash/mapCodeNestedLabeledReplace.ts @@ -13,7 +13,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` myLabel: if (y === x) { console.log("goodbye"); diff --git a/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts b/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts index 9bffa41cf965a..ff2e32158266f 100644 --- a/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts +++ b/tests/cases/fourslash/mapCodeNestedWhileInsertion.ts @@ -12,7 +12,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` while (y === x) { console.log("goodbye"); diff --git a/tests/cases/fourslash/mapCodeNestedWhileReplace.ts b/tests/cases/fourslash/mapCodeNestedWhileReplace.ts index 093d0e9902cb8..e7bb12ef7f7ff 100644 --- a/tests/cases/fourslash/mapCodeNestedWhileReplace.ts +++ b/tests/cases/fourslash/mapCodeNestedWhileReplace.ts @@ -12,7 +12,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` while (x === y) { console.log("goodbye"); diff --git a/tests/cases/fourslash/mapCodeNoChanges.ts b/tests/cases/fourslash/mapCodeNoChanges.ts index 8639add6f9a0d..f721616aafc18 100644 --- a/tests/cases/fourslash/mapCodeNoChanges.ts +++ b/tests/cases/fourslash/mapCodeNoChanges.ts @@ -13,4 +13,4 @@ //// } //// -verify.baselineMapCode(test.ranges(), []); +verify.baselineMapCode([test.ranges()], []); diff --git a/tests/cases/fourslash/mapCodeNoRanges.ts b/tests/cases/fourslash/mapCodeNoRanges.ts index 8a2fa947f0d24..13131195b0179 100644 --- a/tests/cases/fourslash/mapCodeNoRanges.ts +++ b/tests/cases/fourslash/mapCodeNoRanges.ts @@ -9,7 +9,7 @@ //// } //// -verify.baselineMapCode([], [ +verify.baselineMapCode([[]], [ ` function baz() { return 3; diff --git a/tests/cases/fourslash/mapCodeRangeReplacement.ts b/tests/cases/fourslash/mapCodeRangeReplacement.ts index fed9312f92f89..30f2e0f337b7f 100644 --- a/tests/cases/fourslash/mapCodeRangeReplacement.ts +++ b/tests/cases/fourslash/mapCodeRangeReplacement.ts @@ -20,7 +20,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` if (foo == bar) { console.log("huh"); diff --git a/tests/cases/fourslash/mapCodeReplaceUsingRange.ts b/tests/cases/fourslash/mapCodeReplaceUsingRange.ts index 1c13827ac4713..c0630c77f6601 100644 --- a/tests/cases/fourslash/mapCodeReplaceUsingRange.ts +++ b/tests/cases/fourslash/mapCodeReplaceUsingRange.ts @@ -9,7 +9,7 @@ //// }|] //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` function foo() { return 3; diff --git a/tests/cases/fourslash/mapCodeToplevelInsert.ts b/tests/cases/fourslash/mapCodeToplevelInsert.ts index b82aec34b242b..bb6cf164e1f7f 100644 --- a/tests/cases/fourslash/mapCodeToplevelInsert.ts +++ b/tests/cases/fourslash/mapCodeToplevelInsert.ts @@ -1,6 +1,6 @@ /// -// @Filename: /index.ts +// @Filename: /topLevelInsert.ts //// function foo() { //// return 1; //// }[||] @@ -8,7 +8,7 @@ //// return 2; //// } -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` function baz() { return 3; diff --git a/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts b/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts index 2078f12c9a30d..4b217c7714a37 100644 --- a/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts +++ b/tests/cases/fourslash/mapCodeToplevelInsertNoClass.ts @@ -8,7 +8,7 @@ //// return 2; //// } -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` baz() { return 3; diff --git a/tests/cases/fourslash/mapCodeToplevelReplace.ts b/tests/cases/fourslash/mapCodeToplevelReplace.ts index bb763e0407a32..9a10be12d84d6 100644 --- a/tests/cases/fourslash/mapCodeToplevelReplace.ts +++ b/tests/cases/fourslash/mapCodeToplevelReplace.ts @@ -1,6 +1,6 @@ /// -// @Filename: /index.ts +// @Filename: /topLevelReplace.ts //// function foo() { //// return 1; //// }[||] @@ -9,7 +9,7 @@ //// } //// -verify.baselineMapCode(test.ranges(), [ +verify.baselineMapCode([test.ranges()], [ ` function foo() { return 3; From 4b33147d6631249c8e4d4261c0756044e36bb4e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Wed, 22 May 2024 15:18:30 -0700 Subject: [PATCH 14/15] format and lint --- src/harness/fourslashImpl.ts | 2 +- src/services/mapCode.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 6037d20ce1355..ac44525404f5d 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -4533,7 +4533,7 @@ export class TestState { this.applyChanges(edits); focusLocations.forEach(r => { r.sort((a, b) => a.start - b.start); - }) + }); focusLocations.sort((a, b) => a[0].start - b[0].start); for (const subLoc of focusLocations) { for (const { start, length } of subLoc) { diff --git a/src/services/mapCode.ts b/src/services/mapCode.ts index 7ffe68d8eacd1..b87ea5e75301f 100644 --- a/src/services/mapCode.ts +++ b/src/services/mapCode.ts @@ -28,7 +28,6 @@ import { Node, NodeArray, or, - ScriptTarget, some, SourceFile, Statement, From 19fea18b4de54f125b7fd40bf00b59883a7fa375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Wed, 22 May 2024 16:14:27 -0700 Subject: [PATCH 15/15] add plain js file test --- .../mapCodePlainJsInsertion.mapCode.ts | 25 +++++++++++++++++++ .../fourslash/mapCodePlainJsInsertion.ts | 17 +++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 tests/baselines/reference/mapCodePlainJsInsertion.mapCode.ts create mode 100644 tests/cases/fourslash/mapCodePlainJsInsertion.ts diff --git a/tests/baselines/reference/mapCodePlainJsInsertion.mapCode.ts b/tests/baselines/reference/mapCodePlainJsInsertion.mapCode.ts new file mode 100644 index 0000000000000..0cbd78d94f91e --- /dev/null +++ b/tests/baselines/reference/mapCodePlainJsInsertion.mapCode.ts @@ -0,0 +1,25 @@ +// === mapCode === + +// === ORIGINAL === +function foo() { + return 1; +}[||] +function bar() { + return 2; +} +// === INCOMING CHANGES === + +function baz() { + return 3; +} + +// === MAPPED === +function foo() { + return 1; +} +function bar() { + return 2; +} +function baz() { + return 3; +} diff --git a/tests/cases/fourslash/mapCodePlainJsInsertion.ts b/tests/cases/fourslash/mapCodePlainJsInsertion.ts new file mode 100644 index 0000000000000..6580133d7509d --- /dev/null +++ b/tests/cases/fourslash/mapCodePlainJsInsertion.ts @@ -0,0 +1,17 @@ +/// + +// @Filename: /topLevelInsert.js +//// function foo() { +//// return 1; +//// }[||] +//// function bar() { +//// return 2; +//// } + +verify.baselineMapCode([test.ranges()], [ +` +function baz() { + return 3; +} +` +]);