mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
CodeMapper support (#55406)
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -4510,6 +4510,57 @@ export class TestState {
|
||||
|
||||
this.verifyCurrentFileContent(newFileContent);
|
||||
}
|
||||
|
||||
public baselineMapCode(
|
||||
ranges: Range[][],
|
||||
changes: string[] = [],
|
||||
): void {
|
||||
const fileName = this.activeFile.fileName;
|
||||
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,
|
||||
// We trim the leading whitespace stuff just so our test cases can be more readable.
|
||||
changes,
|
||||
focusLocations,
|
||||
this.formatCodeSettings,
|
||||
{},
|
||||
);
|
||||
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) {
|
||||
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 after = this.getFileContent(fileName);
|
||||
const baseline = `
|
||||
// === ORIGINAL ===
|
||||
${before}
|
||||
// === INCOMING CHANGES ===
|
||||
${changes.join("\n// ---\n")}
|
||||
// === MAPPED ===
|
||||
${after}`;
|
||||
this.baseline("mapCode", baseline, ".mapCode.ts");
|
||||
}
|
||||
}
|
||||
|
||||
function updateTextRangeForTextChanges({ pos, end }: ts.TextRange, textChanges: readonly ts.TextChange[]): ts.TextRange {
|
||||
|
||||
@@ -239,6 +239,10 @@ export class VerifyNegatable {
|
||||
public uncommentSelection(newFileContent: string) {
|
||||
this.state.uncommentSelection(newFileContent);
|
||||
}
|
||||
|
||||
public baselineMapCode(ranges: FourSlash.Range[][], changes: string[] = []): void {
|
||||
this.state.baselineMapCode(ranges, changes);
|
||||
}
|
||||
}
|
||||
|
||||
export class Verify extends VerifyNegatable {
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -1906,6 +1906,26 @@ export class Session<TMessage = string> 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<TMessage = string> 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) {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
/* Generated file to emulate the ts.MapCode namespace. */
|
||||
|
||||
export * from "../mapCode.js";
|
||||
@@ -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 };
|
||||
|
||||
@@ -0,0 +1,323 @@
|
||||
import {
|
||||
Block,
|
||||
ClassElement,
|
||||
ClassLikeDeclaration,
|
||||
createSourceFile,
|
||||
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,
|
||||
some,
|
||||
SourceFile,
|
||||
Statement,
|
||||
SyntaxKind,
|
||||
textChanges,
|
||||
TextSpan,
|
||||
TypeElement,
|
||||
UserPreferences,
|
||||
} from "./_namespaces/ts.js";
|
||||
import { ChangeTracker } from "./textChanges.js";
|
||||
|
||||
/** @internal */
|
||||
export function mapCode(
|
||||
sourceFile: SourceFile,
|
||||
contents: string[],
|
||||
focusLocations: TextSpan[][] | undefined,
|
||||
host: LanguageServiceHost,
|
||||
formatContext: formatting.FormatContext,
|
||||
preferences: UserPreferences,
|
||||
): FileTextChanges[] {
|
||||
return textChanges.ChangeTracker.with(
|
||||
{ host, formatContext, preferences },
|
||||
changeTracker => {
|
||||
const parsed = contents.map(c => parse(sourceFile, c));
|
||||
const flattenedLocations = focusLocations && flatten(focusLocations);
|
||||
for (const nodes of parsed) {
|
||||
placeNodeGroup(
|
||||
sourceFile,
|
||||
changeTracker,
|
||||
nodes,
|
||||
flattenedLocations,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to parse something into either "top-level" statements, or into blocks
|
||||
* of class-context definitions.
|
||||
*/
|
||||
function parse(sourceFile: SourceFile, content: string): NodeArray<Node> {
|
||||
// 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,
|
||||
sourceFile.languageVersion,
|
||||
/*setParentNodes*/ true,
|
||||
sourceFile.scriptKind,
|
||||
),
|
||||
body: (sf: SourceFile) => sf.statements,
|
||||
},
|
||||
{
|
||||
parse: () =>
|
||||
createSourceFile(
|
||||
"__mapcode_class_content_nodes.ts",
|
||||
`class __class {\n${content}\n}`,
|
||||
sourceFile.languageVersion,
|
||||
/*setParentNodes*/ true,
|
||||
sourceFile.scriptKind,
|
||||
),
|
||||
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<Node>,
|
||||
focusLocations?: TextSpan[],
|
||||
) {
|
||||
if (isClassElement(changes[0]) || isTypeElement(changes[0])) {
|
||||
placeClassNodeGroup(
|
||||
originalFile,
|
||||
changeTracker,
|
||||
changes as NodeArray<ClassElement>,
|
||||
focusLocations,
|
||||
);
|
||||
}
|
||||
else {
|
||||
placeStatements(
|
||||
originalFile,
|
||||
changeTracker,
|
||||
changes as NodeArray<Statement>,
|
||||
focusLocations,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function placeClassNodeGroup(
|
||||
originalFile: SourceFile,
|
||||
changeTracker: ChangeTracker,
|
||||
changes: NodeArray<ClassElement> | NodeArray<TypeElement>,
|
||||
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) {
|
||||
// No class? don't insert.
|
||||
return;
|
||||
}
|
||||
|
||||
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<ClassElement | TypeElement>,
|
||||
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<Statement>,
|
||||
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<Statement> = 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<Node>) {
|
||||
resetNodePositions(node);
|
||||
node.parent = undefined!;
|
||||
}
|
||||
|
||||
function resetNodePositions(node: Mutable<Node>) {
|
||||
node.pos = -1;
|
||||
node.end = -1;
|
||||
node.forEachChild(resetNodePositions);
|
||||
}
|
||||
@@ -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): 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) {
|
||||
|
||||
@@ -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): readonly FileTextChanges[];
|
||||
|
||||
dispose(): void;
|
||||
getPasteEdits(
|
||||
args: PasteEditsArgs,
|
||||
|
||||
+29
@@ -121,6 +121,7 @@ declare namespace ts {
|
||||
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls",
|
||||
ProvideInlayHints = "provideInlayHints",
|
||||
WatchChange = "watchChange",
|
||||
MapCode = "mapCode",
|
||||
}
|
||||
/**
|
||||
* A TypeScript Server message
|
||||
@@ -1769,6 +1770,33 @@ declare namespace ts {
|
||||
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.
|
||||
*/
|
||||
@@ -3468,6 +3496,7 @@ declare namespace ts {
|
||||
private getLinkedEditingRange;
|
||||
private getDocumentHighlights;
|
||||
private provideInlayHints;
|
||||
private mapCode;
|
||||
private setCompilerOptionsForInferredProjects;
|
||||
private getProjectInfo;
|
||||
private getProjectInfoWorker;
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// === mapCode ===
|
||||
|
||||
// === ORIGINAL ===
|
||||
class MyClass {[||]
|
||||
}
|
||||
|
||||
// === INCOMING CHANGES ===
|
||||
|
||||
if (false) {
|
||||
return "hello";
|
||||
}
|
||||
|
||||
// === MAPPED ===
|
||||
class MyClass {
|
||||
}
|
||||
|
||||
if (false) {
|
||||
return "hello";
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// === 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// === 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// === 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// === 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// === 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");
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// === mapCode ===
|
||||
|
||||
// === ORIGINAL ===
|
||||
function foo() {
|
||||
return 1;
|
||||
}[||]
|
||||
function bar() {
|
||||
return 2;
|
||||
}
|
||||
// === INCOMING CHANGES ===
|
||||
|
||||
baz() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
// === MAPPED ===
|
||||
function foo() {
|
||||
return 1;
|
||||
}
|
||||
function bar() {
|
||||
return 2;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// === 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;
|
||||
}
|
||||
@@ -452,6 +452,7 @@ declare namespace FourSlashInterface {
|
||||
copiedFrom?: { file: string, range: { pos: number, end: number }[] };
|
||||
}
|
||||
}): void;
|
||||
baselineMapCode(ranges: Range[][], changes: string[]): void;
|
||||
}
|
||||
class edit {
|
||||
caretPosition(): Marker;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// class MyClass {[||]
|
||||
//// }
|
||||
////
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
if (false) {
|
||||
return "hello";
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,39 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @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()], [
|
||||
`
|
||||
if (x === y) {
|
||||
return x + y;
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,24 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// class MyClass {[||]
|
||||
//// x = 1;
|
||||
//// foo() {
|
||||
//// return 1;
|
||||
//// }
|
||||
//// bar() {
|
||||
//// return 2;
|
||||
//// }
|
||||
//// baz() {
|
||||
//// return 3;
|
||||
//// }
|
||||
//// }
|
||||
////
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
quux() {
|
||||
return 4;
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,24 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// class MyClass {
|
||||
//// x = 1;
|
||||
//// foo() {
|
||||
//// return 1;
|
||||
//// }
|
||||
//// bar() {[||]
|
||||
//// return 2;
|
||||
//// }
|
||||
//// baz() {
|
||||
//// return 3;
|
||||
//// }
|
||||
//// }
|
||||
////
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
bar() {
|
||||
return 'hello';
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,26 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// class MyClass {[||]
|
||||
//// x = 1;
|
||||
//// foo() {
|
||||
//// return 1;
|
||||
//// }
|
||||
//// bar() {
|
||||
//// return 2;
|
||||
//// }
|
||||
//// }
|
||||
////
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
x = 3;
|
||||
bar() {
|
||||
return 'hello';
|
||||
}
|
||||
baz() {
|
||||
return 3;
|
||||
}
|
||||
y = 2;
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,38 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @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|];
|
||||
//// }
|
||||
////
|
||||
|
||||
const [r0, r1, r2] = test.ranges();
|
||||
verify.baselineMapCode([[r0], [r2, r1]], [
|
||||
`
|
||||
if (x === y) {
|
||||
console.log("goodbye");
|
||||
console.log("world");
|
||||
}
|
||||
`,
|
||||
`
|
||||
function bar() {
|
||||
return 3;
|
||||
}
|
||||
`,
|
||||
`
|
||||
method() {
|
||||
return 'nope';
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,26 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// class MyClass {
|
||||
//// x = 1;
|
||||
//// foo() {
|
||||
//// return 1;
|
||||
//// }
|
||||
//// bar() {
|
||||
//// if (true)[||] {
|
||||
//// return 2;
|
||||
//// }
|
||||
//// }
|
||||
//// baz() {
|
||||
//// return 3;
|
||||
//// }
|
||||
//// }
|
||||
////
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
if (false) {
|
||||
return "hello";
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,26 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// class MyClass {
|
||||
//// x = 1;
|
||||
//// foo() {
|
||||
//// return 1;
|
||||
//// }
|
||||
//// bar() {
|
||||
//// if (true) [||]{
|
||||
//// return 2;
|
||||
//// }
|
||||
//// }
|
||||
//// baz() {
|
||||
//// return 3;
|
||||
//// }
|
||||
//// }
|
||||
////
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
if (true) {
|
||||
return "hello";
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,22 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @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()], [
|
||||
`
|
||||
for (let j = 0; j < 10; j++) {
|
||||
console.log("goodbye");
|
||||
console.log("world");
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,20 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// function foo() {
|
||||
//// for (const x of [1, 2, 3])[||] {
|
||||
//// console.log("hello");
|
||||
//// console.log("you");
|
||||
//// }
|
||||
//// return 1;
|
||||
//// }
|
||||
////
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
for (const y of [1, 2, 3]) {
|
||||
console.log("goodbye");
|
||||
console.log("world");
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,20 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// function foo() {
|
||||
//// for (const x of [1, 2, 3]) [||]{
|
||||
//// console.log("hello");
|
||||
//// console.log("you");
|
||||
//// }
|
||||
//// return 1;
|
||||
//// }
|
||||
////
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
for (const x of [1, 2, 3]) {
|
||||
console.log("goodbye");
|
||||
console.log("world");
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,20 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// function foo() {
|
||||
//// for (let x = 0; x < 10; x++) [||]{
|
||||
//// console.log("hello");
|
||||
//// console.log("you");
|
||||
//// }
|
||||
//// return 1;
|
||||
//// }
|
||||
////
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
for (let x = 0; x < 10; x++) {
|
||||
console.log("goodbye");
|
||||
console.log("world");
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,22 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @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()], [
|
||||
`
|
||||
if (y === x) {
|
||||
console.log("goodbye");
|
||||
console.log("world");
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,22 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @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()], [
|
||||
`
|
||||
if (x === y) {
|
||||
console.log("goodbye");
|
||||
console.log("world");
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,24 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @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()], [
|
||||
`
|
||||
otherLabel: if (y === x) {
|
||||
console.log("goodbye");
|
||||
console.log("world");
|
||||
break otherLabel;
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,24 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @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()], [
|
||||
`
|
||||
myLabel: if (y === x) {
|
||||
console.log("goodbye");
|
||||
console.log("world");
|
||||
break myLabel;
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,22 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @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()], [
|
||||
`
|
||||
while (y === x) {
|
||||
console.log("goodbye");
|
||||
console.log("world");
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,22 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @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()], [
|
||||
`
|
||||
while (x === y) {
|
||||
console.log("goodbye");
|
||||
console.log("world");
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,16 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// function foo() {
|
||||
//// return 1;
|
||||
//// }
|
||||
//// [||]
|
||||
//// function bar() {
|
||||
//// return 2;
|
||||
//// }
|
||||
//// function baz() {
|
||||
//// return 3;
|
||||
//// }
|
||||
////
|
||||
|
||||
verify.baselineMapCode([test.ranges()], []);
|
||||
@@ -0,0 +1,19 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// function foo() {
|
||||
//// return 1;
|
||||
//// }
|
||||
//// function bar() {
|
||||
//// return 2;
|
||||
//// }
|
||||
////
|
||||
|
||||
verify.baselineMapCode([[]], [
|
||||
`
|
||||
function baz() {
|
||||
return 3;
|
||||
}
|
||||
`
|
||||
]);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /topLevelInsert.js
|
||||
//// function foo() {
|
||||
//// return 1;
|
||||
//// }[||]
|
||||
//// function bar() {
|
||||
//// return 2;
|
||||
//// }
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
function baz() {
|
||||
return 3;
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,33 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @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()], [
|
||||
`
|
||||
if (foo == bar) {
|
||||
console.log("huh");
|
||||
}
|
||||
|
||||
function baz() {
|
||||
return 'baz';
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,18 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// [|function foo() {
|
||||
//// return 1;
|
||||
//// }[||]
|
||||
//// function bar() {
|
||||
//// return [|2;|]
|
||||
//// }|]
|
||||
////
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
function foo() {
|
||||
return 3;
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,17 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /topLevelInsert.ts
|
||||
//// function foo() {
|
||||
//// return 1;
|
||||
//// }[||]
|
||||
//// function bar() {
|
||||
//// return 2;
|
||||
//// }
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
function baz() {
|
||||
return 3;
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,17 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// function foo() {
|
||||
//// return 1;
|
||||
//// }[||]
|
||||
//// function bar() {
|
||||
//// return 2;
|
||||
//// }
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
baz() {
|
||||
return 3;
|
||||
}
|
||||
`
|
||||
]);
|
||||
@@ -0,0 +1,18 @@
|
||||
///<reference path="fourslash.ts"/>
|
||||
|
||||
// @Filename: /topLevelReplace.ts
|
||||
//// function foo() {
|
||||
//// return 1;
|
||||
//// }[||]
|
||||
//// function bar() {
|
||||
//// return 2;
|
||||
//// }
|
||||
////
|
||||
|
||||
verify.baselineMapCode([test.ranges()], [
|
||||
`
|
||||
function foo() {
|
||||
return 3;
|
||||
}
|
||||
`
|
||||
]);
|
||||
Reference in New Issue
Block a user