1// Some tests have trailing whitespace 2 3namespace ts { 4 describe("unittests:: services:: textChanges", () => { 5 function findChild(name: string, n: Node) { 6 return find(n)!; 7 8 function find(node: Node): Node | undefined { 9 if (isDeclaration(node) && node.name && isIdentifier(node.name) && node.name.escapedText === name) { 10 return node; 11 } 12 else { 13 return forEachChild(node, find); 14 } 15 } 16 } 17 18 const printerOptions = { newLine: NewLineKind.LineFeed }; 19 const newLineCharacter = getNewLineCharacter(printerOptions); 20 21 function getRuleProvider(placeOpenBraceOnNewLineForFunctions: boolean): formatting.FormatContext { 22 return formatting.getFormatContext(placeOpenBraceOnNewLineForFunctions ? { ...testFormatSettings, placeOpenBraceOnNewLineForFunctions: true } : testFormatSettings, notImplementedHost); 23 } 24 25 // validate that positions that were recovered from the printed text actually match positions that will be created if the same text is parsed. 26 function verifyPositions(node: Node, text: string): void { 27 const nodeList = flattenNodes(node); 28 const sourceFile = createSourceFile("f.ts", text, ScriptTarget.ES2015); 29 const parsedNodeList = flattenNodes(sourceFile.statements[0]); 30 zipWith(nodeList, parsedNodeList, (left, right) => { 31 Debug.assert(left.pos === right.pos); 32 Debug.assert(left.end === right.end); 33 }); 34 35 function flattenNodes(n: Node) { 36 const data: (Node | NodeArray<Node>)[] = []; 37 walk(n); 38 return data; 39 40 function walk(n: Node | NodeArray<Node>): void { 41 data.push(n); 42 return isArray(n) ? forEach(n, walk) : forEachChild(n, walk, walk); 43 } 44 } 45 } 46 47 function runSingleFileTest(caption: string, placeOpenBraceOnNewLineForFunctions: boolean, text: string, validateNodes: boolean, testBlock: (sourceFile: SourceFile, changeTracker: textChanges.ChangeTracker) => void) { 48 it(caption, () => { 49 const sourceFile = createSourceFile("source.ts", text, ScriptTarget.ES2015, /*setParentNodes*/ true); 50 const rulesProvider = getRuleProvider(placeOpenBraceOnNewLineForFunctions); 51 const changeTracker = new textChanges.ChangeTracker(newLineCharacter, rulesProvider); 52 testBlock(sourceFile, changeTracker); 53 const changes = changeTracker.getChanges(validateNodes ? verifyPositions : undefined); 54 assert.equal(changes.length, 1); 55 assert.equal(changes[0].fileName, sourceFile.fileName); 56 const modified = textChanges.applyChanges(sourceFile.text, changes[0].textChanges); 57 Harness.Baseline.runBaseline(`textChanges/${caption}.js`, `===ORIGINAL===${newLineCharacter}${text}${newLineCharacter}===MODIFIED===${newLineCharacter}${modified}`); 58 }); 59 } 60 61 { 62 const text = ` 63namespace M 64{ 65 namespace M2 66 { 67 function foo() { 68 // comment 1 69 const x = 1; 70 71 /** 72 * comment 2 line 1 73 * comment 2 line 2 74 */ 75 function f() { 76 return 100; 77 } 78 const y = 2; // comment 3 79 return 1; 80 } 81 } 82}`; 83 runSingleFileTest("extractMethodLike", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 84 const statements = (<FunctionDeclaration>findChild("foo", sourceFile)).body!.statements.slice(1); 85 const newFunction = factory.createFunctionDeclaration( 86 /*decorators*/ undefined, 87 /*modifiers*/ undefined, 88 /*asteriskToken*/ undefined, 89 /*name*/ "bar", 90 /*typeParameters*/ undefined, 91 /*parameters*/ emptyArray, 92 /*type*/ factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), 93 /*body */ factory.createBlock(statements) 94 ); 95 96 changeTracker.insertNodeBefore(sourceFile, /*before*/findChild("M2", sourceFile), newFunction); 97 98 // replace statements with return statement 99 const newStatement = factory.createReturnStatement( 100 factory.createCallExpression( 101 /*expression*/ newFunction.name!, 102 /*typeArguments*/ undefined, 103 /*argumentsArray*/ emptyArray 104 )); 105 changeTracker.replaceNodeRange(sourceFile, statements[0], last(statements), newStatement, { suffix: newLineCharacter }); 106 }); 107 } 108 { 109 const text = ` 110function foo() { 111 return 1; 112} 113 114function bar() { 115 return 2; 116} 117`; 118 runSingleFileTest("deleteRange1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 119 changeTracker.deleteRange(sourceFile, { pos: text.indexOf("function foo"), end: text.indexOf("function bar") }); 120 }); 121 } 122 function findVariableStatementContaining(name: string, sourceFile: SourceFile): VariableStatement { 123 return cast(findVariableDeclarationContaining(name, sourceFile).parent.parent, isVariableStatement); 124 } 125 function findVariableDeclarationContaining(name: string, sourceFile: SourceFile): VariableDeclaration { 126 return cast(findChild(name, sourceFile), isVariableDeclaration); 127 } 128 const { deleteNode } = textChanges; 129 { 130 const text = ` 131var x = 1; // some comment - 1 132/** 133 * comment 2 134 */ 135var y = 2; // comment 3 136var z = 3; // comment 4 137`; 138 runSingleFileTest("deleteNode1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 139 deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile)); 140 }); 141 runSingleFileTest("deleteNode2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 142 deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude }); 143 }); 144 runSingleFileTest("deleteNode3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 145 deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude }); 146 }); 147 runSingleFileTest("deleteNode4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 148 deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude }); 149 }); 150 runSingleFileTest("deleteNode5", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 151 deleteNode(changeTracker, sourceFile, findVariableStatementContaining("x", sourceFile)); 152 }); 153 } 154 { 155 const text = ` 156// comment 1 157var x = 1; // comment 2 158// comment 3 159var y = 2; // comment 4 160var z = 3; // comment 5 161// comment 6 162var a = 4; // comment 7 163`; 164 runSingleFileTest("deleteNodeRange1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 165 changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile)); 166 }); 167 runSingleFileTest("deleteNodeRange2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 168 changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), 169 { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude }); 170 }); 171 runSingleFileTest("deleteNodeRange3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 172 changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), 173 { trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude }); 174 }); 175 runSingleFileTest("deleteNodeRange4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 176 changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), 177 { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude }); 178 }); 179 } 180 function createTestVariableDeclaration(name: string) { 181 return factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, /*type*/ undefined, factory.createObjectLiteralExpression([factory.createPropertyAssignment("p1", factory.createNumericLiteral(1))], /*multiline*/ true)); 182 } 183 function createTestClass() { 184 return factory.createClassDeclaration( 185 /*decorators*/ undefined, 186 [ 187 factory.createToken(SyntaxKind.PublicKeyword) 188 ], 189 "class1", 190 /*typeParameters*/ undefined, 191 [ 192 factory.createHeritageClause( 193 SyntaxKind.ImplementsKeyword, 194 [ 195 factory.createExpressionWithTypeArguments(factory.createIdentifier("interface1"), /*typeArguments*/ undefined) 196 ] 197 ) 198 ], 199 [ 200 factory.createPropertyDeclaration( 201 /*decorators*/ undefined, 202 /*modifiers*/ undefined, 203 "property1", 204 /*questionToken*/ undefined, 205 factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword), 206 /*initializer*/ undefined 207 ) 208 ] 209 ); 210 } 211 { 212 const text = ` 213// comment 1 214var x = 1; // comment 2 215// comment 3 216var y = 2; // comment 4 217var z = 3; // comment 5 218// comment 6 219var a = 4; // comment 7`; 220 runSingleFileTest("replaceRange", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 221 changeTracker.replaceRange(sourceFile, { pos: text.indexOf("var y"), end: text.indexOf("var a") }, createTestClass(), { suffix: newLineCharacter }); 222 }); 223 runSingleFileTest("replaceRangeWithForcedIndentation", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 224 changeTracker.replaceRange(sourceFile, { pos: text.indexOf("var y"), end: text.indexOf("var a") }, createTestClass(), { suffix: newLineCharacter, indentation: 8, delta: 0 }); 225 }); 226 227 runSingleFileTest("replaceRangeNoLineBreakBefore", /*placeOpenBraceOnNewLineForFunctions*/ true, `const x = 1, y = "2";`, /*validateNodes*/ false, (sourceFile, changeTracker) => { 228 const newNode = createTestVariableDeclaration("z1"); 229 changeTracker.replaceRange(sourceFile, { pos: sourceFile.text.indexOf("y"), end: sourceFile.text.indexOf(";") }, newNode); 230 }); 231 } 232 { 233 const text = ` 234namespace A { 235 const x = 1, y = "2"; 236} 237`; 238 runSingleFileTest("replaceNode1NoLineBreakBefore", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 239 const newNode = createTestVariableDeclaration("z1"); 240 changeTracker.replaceNode(sourceFile, findChild("y", sourceFile), newNode); 241 }); 242 } 243 { 244 const text = ` 245// comment 1 246var x = 1; // comment 2 247// comment 3 248var y = 2; // comment 4 249var z = 3; // comment 5 250// comment 6 251var a = 4; // comment 7`; 252 runSingleFileTest("replaceNode1", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 253 changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter }); 254 }); 255 runSingleFileTest("replaceNode2", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 256 changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, suffix: newLineCharacter, prefix: newLineCharacter }); 257 }); 258 runSingleFileTest("replaceNode3", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 259 changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude, suffix: newLineCharacter }); 260 }); 261 runSingleFileTest("replaceNode4", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 262 changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude }); 263 }); 264 runSingleFileTest("replaceNode5", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 265 changeTracker.replaceNode(sourceFile, findVariableStatementContaining("x", sourceFile), createTestClass(), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude }); 266 }); 267 } 268 { 269 const text = ` 270// comment 1 271var x = 1; // comment 2 272// comment 3 273var y = 2; // comment 4 274var z = 3; // comment 5 275// comment 6 276var a = 4; // comment 7`; 277 runSingleFileTest("replaceNodeRange1", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 278 changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { suffix: newLineCharacter }); 279 }); 280 runSingleFileTest("replaceNodeRange2", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 281 changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, suffix: newLineCharacter, prefix: newLineCharacter }); 282 }); 283 runSingleFileTest("replaceNodeRange3", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 284 changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude, suffix: newLineCharacter }); 285 }); 286 runSingleFileTest("replaceNodeRange4", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 287 changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude }); 288 }); 289 } 290 { 291 const text = ` 292// comment 1 293var x = 1; // comment 2 294// comment 3 295var y; // comment 4 296var z = 3; // comment 5 297// comment 6 298var a = 4; // comment 7`; 299 runSingleFileTest("insertNodeBefore3", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 300 changeTracker.insertNodeBefore(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass()); 301 }); 302 runSingleFileTest("insertNodeAfterVariableDeclaration", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 303 changeTracker.insertNodeAfter(sourceFile, findVariableDeclarationContaining("y", sourceFile), createTestVariableDeclaration("z1")); 304 }); 305 } 306 { 307 const text = ` 308namespace M { 309 // comment 1 310 var x = 1; // comment 2 311 // comment 3 312 var y; // comment 4 313 var z = 3; // comment 5 314 // comment 6 315 var a = 4; // comment 7 316}`; 317 runSingleFileTest("insertNodeBefore1", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 318 changeTracker.insertNodeBefore(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass()); 319 }); 320 runSingleFileTest("insertNodeBefore2", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 321 changeTracker.insertNodeBefore(sourceFile, findChild("M", sourceFile), createTestClass()); 322 }); 323 runSingleFileTest("insertNodeAfter1", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 324 changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass()); 325 }); 326 runSingleFileTest("insertNodeAfter2", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { 327 changeTracker.insertNodeAfter(sourceFile, findChild("M", sourceFile), createTestClass()); 328 }); 329 } 330 331 function findConstructor(sourceFile: SourceFile): ConstructorDeclaration { 332 const classDecl = <ClassDeclaration>sourceFile.statements[0]; 333 return find<ClassElement, ConstructorDeclaration>(classDecl.members, (m): m is ConstructorDeclaration => isConstructorDeclaration(m) && !!m.body)!; 334 } 335 function createTestSuperCall() { 336 const superCall = factory.createCallExpression( 337 factory.createSuper(), 338 /*typeArguments*/ undefined, 339 /*argumentsArray*/ emptyArray 340 ); 341 return factory.createExpressionStatement(superCall); 342 } 343 344 { 345 const text1 = ` 346class A { 347 constructor() { 348 } 349} 350`; 351 runSingleFileTest("insertNodeAtConstructorStart", /*placeOpenBraceOnNewLineForFunctions*/ false, text1, /*validateNodes*/ false, (sourceFile, changeTracker) => { 352 changeTracker.insertNodeAtConstructorStart(sourceFile, findConstructor(sourceFile), createTestSuperCall()); 353 }); 354 const text2 = ` 355class A { 356 constructor() { 357 var x = 1; 358 } 359} 360`; 361 runSingleFileTest("insertNodeAfter4", /*placeOpenBraceOnNewLineForFunctions*/ false, text2, /*validateNodes*/ false, (sourceFile, changeTracker) => { 362 changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), createTestSuperCall()); 363 }); 364 const text3 = ` 365class A { 366 constructor() { 367 368 } 369} 370`; 371 runSingleFileTest("insertNodeAtConstructorStart-block with newline", /*placeOpenBraceOnNewLineForFunctions*/ false, text3, /*validateNodes*/ false, (sourceFile, changeTracker) => { 372 changeTracker.insertNodeAtConstructorStart(sourceFile, findConstructor(sourceFile), createTestSuperCall()); 373 }); 374 } 375 { 376 const text = `var a = 1, b = 2, c = 3;`; 377 runSingleFileTest("deleteNodeInList1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 378 changeTracker.delete(sourceFile, findChild("a", sourceFile)); 379 }); 380 runSingleFileTest("deleteNodeInList2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 381 changeTracker.delete(sourceFile, findChild("b", sourceFile)); 382 }); 383 runSingleFileTest("deleteNodeInList3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 384 changeTracker.delete(sourceFile, findChild("c", sourceFile)); 385 }); 386 } 387 { 388 const text = `var a = 1,b = 2,c = 3;`; 389 runSingleFileTest("deleteNodeInList1_1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 390 changeTracker.delete(sourceFile, findChild("a", sourceFile)); 391 }); 392 runSingleFileTest("deleteNodeInList2_1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 393 changeTracker.delete(sourceFile, findChild("b", sourceFile)); 394 }); 395 runSingleFileTest("deleteNodeInList3_1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 396 changeTracker.delete(sourceFile, findChild("c", sourceFile)); 397 }); 398 } 399 { 400 const text = ` 401namespace M { 402 var a = 1, 403 b = 2, 404 c = 3; 405}`; 406 runSingleFileTest("deleteNodeInList4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 407 changeTracker.delete(sourceFile, findChild("a", sourceFile)); 408 }); 409 runSingleFileTest("deleteNodeInList5", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 410 changeTracker.delete(sourceFile, findChild("b", sourceFile)); 411 }); 412 runSingleFileTest("deleteNodeInList6", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 413 changeTracker.delete(sourceFile, findChild("c", sourceFile)); 414 }); 415 } 416 { 417 const text = ` 418namespace M { 419 var a = 1, // comment 1 420 // comment 2 421 b = 2, // comment 3 422 // comment 4 423 c = 3; // comment 5 424}`; 425 runSingleFileTest("deleteNodeInList4_1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 426 changeTracker.delete(sourceFile, findChild("a", sourceFile)); 427 }); 428 runSingleFileTest("deleteNodeInList5_1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 429 changeTracker.delete(sourceFile, findChild("b", sourceFile)); 430 }); 431 runSingleFileTest("deleteNodeInList6_1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 432 changeTracker.delete(sourceFile, findChild("c", sourceFile)); 433 }); 434 } 435 { 436 const text = ` 437function foo(a: number, b: string, c = true) { 438 return 1; 439}`; 440 runSingleFileTest("deleteNodeInList7", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 441 changeTracker.delete(sourceFile, findChild("a", sourceFile)); 442 }); 443 runSingleFileTest("deleteNodeInList8", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 444 changeTracker.delete(sourceFile, findChild("b", sourceFile)); 445 }); 446 runSingleFileTest("deleteNodeInList9", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 447 changeTracker.delete(sourceFile, findChild("c", sourceFile)); 448 }); 449 } 450 { 451 const text = ` 452function foo(a: number,b: string,c = true) { 453 return 1; 454}`; 455 runSingleFileTest("deleteNodeInList10", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 456 changeTracker.delete(sourceFile, findChild("a", sourceFile)); 457 }); 458 runSingleFileTest("deleteNodeInList11", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 459 changeTracker.delete(sourceFile, findChild("b", sourceFile)); 460 }); 461 runSingleFileTest("deleteNodeInList12", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 462 changeTracker.delete(sourceFile, findChild("c", sourceFile)); 463 }); 464 } 465 { 466 const text = ` 467function foo( 468 a: number, 469 b: string, 470 c = true) { 471 return 1; 472}`; 473 runSingleFileTest("deleteNodeInList13", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 474 changeTracker.delete(sourceFile, findChild("a", sourceFile)); 475 }); 476 runSingleFileTest("deleteNodeInList14", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 477 changeTracker.delete(sourceFile, findChild("b", sourceFile)); 478 }); 479 runSingleFileTest("deleteNodeInList15", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 480 changeTracker.delete(sourceFile, findChild("c", sourceFile)); 481 }); 482 } 483 { 484 const text = ` 485const x = 1, y = 2;`; 486 runSingleFileTest("insertNodeInListAfter1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 487 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); 488 }); 489 runSingleFileTest("insertNodeInListAfter2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 490 changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); 491 }); 492 } 493 { 494 const text = ` 495const /*x*/ x = 1, /*y*/ y = 2;`; 496 runSingleFileTest("insertNodeInListAfter3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 497 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); 498 }); 499 runSingleFileTest("insertNodeInListAfter4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 500 changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); 501 }); 502 } 503 { 504 const text = ` 505const x = 1;`; 506 runSingleFileTest("insertNodeInListAfter5", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 507 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); 508 }); 509 } 510 { 511 const text = ` 512const x = 1, 513 y = 2;`; 514 runSingleFileTest("insertNodeInListAfter6", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 515 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); 516 }); 517 runSingleFileTest("insertNodeInListAfter7", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 518 changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); 519 }); 520 } 521 { 522 const text = ` 523const /*x*/ x = 1, 524 /*y*/ y = 2;`; 525 runSingleFileTest("insertNodeInListAfter8", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 526 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); 527 }); 528 runSingleFileTest("insertNodeInListAfter9", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 529 changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); 530 }); 531 } 532 { 533 const text = ` 534import { 535 x 536} from "bar"`; 537 runSingleFileTest("insertNodeInListAfter10", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 538 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(factory.createIdentifier("b"), factory.createIdentifier("a"))); 539 }); 540 } 541 { 542 const text = ` 543import { 544 x // this is x 545} from "bar"`; 546 runSingleFileTest("insertNodeInListAfter11", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 547 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(factory.createIdentifier("b"), factory.createIdentifier("a"))); 548 }); 549 } 550 { 551 const text = ` 552import { 553 x 554} from "bar"`; 555 runSingleFileTest("insertNodeInListAfter12", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 556 // eslint-disable-next-line boolean-trivia 557 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a"))); 558 }); 559 } 560 { 561 const text = ` 562import { 563 x // this is x 564} from "bar"`; 565 runSingleFileTest("insertNodeInListAfter13", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 566 // eslint-disable-next-line boolean-trivia 567 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a"))); 568 }); 569 } 570 { 571 const text = ` 572import { 573 x0, 574 x 575} from "bar"`; 576 runSingleFileTest("insertNodeInListAfter14", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 577 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(factory.createIdentifier("b"), factory.createIdentifier("a"))); 578 }); 579 } 580 { 581 const text = ` 582import { 583 x0, 584 x // this is x 585} from "bar"`; 586 runSingleFileTest("insertNodeInListAfter15", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 587 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(factory.createIdentifier("b"), factory.createIdentifier("a"))); 588 }); 589 } 590 { 591 const text = ` 592import { 593 x0, 594 x 595} from "bar"`; 596 runSingleFileTest("insertNodeInListAfter16", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 597 // eslint-disable-next-line boolean-trivia 598 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a"))); 599 }); 600 } 601 { 602 const text = ` 603import { 604 x0, 605 x // this is x 606} from "bar"`; 607 runSingleFileTest("insertNodeInListAfter17", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 608 // eslint-disable-next-line boolean-trivia 609 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a"))); 610 }); 611 } 612 { 613 const text = ` 614import { 615 x0, x 616} from "bar"`; 617 runSingleFileTest("insertNodeInListAfter18", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 618 // eslint-disable-next-line boolean-trivia 619 changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a"))); 620 }); 621 } 622 { 623 const runTest = (name: string, text: string) => runSingleFileTest(name, /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 624 for (const specifier of ["x3", "x4", "x5"]) { 625 // eslint-disable-next-line boolean-trivia 626 changeTracker.insertNodeInListAfter(sourceFile, findChild("x2", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier(specifier))); 627 } 628 }); 629 630 const crlfText = "import {\r\nx1,\r\nx2\r\n} from \"bar\";"; 631 runTest("insertNodeInListAfter19", crlfText); 632 633 const lfText = "import {\nx1,\nx2\n} from \"bar\";"; 634 runTest("insertNodeInListAfter20", lfText); 635 } 636 { 637 const text = ` 638class A { 639 x; 640}`; 641 runSingleFileTest("insertNodeAfterMultipleNodes", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 642 const newNodes = []; 643 for (let i = 0; i < 11 /*error doesn't occur with fewer nodes*/; ++i) { 644 newNodes.push( 645 // eslint-disable-next-line boolean-trivia 646 factory.createPropertyDeclaration(undefined, undefined, i + "", undefined, undefined, undefined)); 647 } 648 const insertAfter = findChild("x", sourceFile); 649 for (const newNode of newNodes) { 650 changeTracker.insertNodeAfter(sourceFile, insertAfter, newNode); 651 } 652 }); 653 } 654 { 655 const text = ` 656class A { 657 x 658} 659`; 660 runSingleFileTest("insertNodeAfterInClass1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 661 // eslint-disable-next-line boolean-trivia 662 changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), factory.createPropertyDeclaration(undefined, undefined, "a", undefined, factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined)); 663 }); 664 } 665 { 666 const text = ` 667class A { 668 x; 669} 670`; 671 runSingleFileTest("insertNodeAfterInClass2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 672 // eslint-disable-next-line boolean-trivia 673 changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), factory.createPropertyDeclaration(undefined, undefined, "a", undefined, factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined)); 674 }); 675 } 676 { 677 const text = ` 678class A { 679 x; 680 y = 1; 681} 682`; 683 runSingleFileTest("deleteNodeAfterInClass1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 684 deleteNode(changeTracker, sourceFile, findChild("x", sourceFile)); 685 }); 686 } 687 { 688 const text = ` 689class A { 690 x 691 y = 1; 692} 693`; 694 runSingleFileTest("deleteNodeAfterInClass2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 695 deleteNode(changeTracker, sourceFile, findChild("x", sourceFile)); 696 }); 697 } 698 { 699 const text = ` 700class A { 701 x = foo 702} 703`; 704 runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 705 const newNode = factory.createPropertyDeclaration( 706 /*decorators*/ undefined, 707 /*modifiers*/ undefined, 708 factory.createComputedPropertyName(factory.createNumericLiteral(1)), 709 /*questionToken*/ undefined, 710 factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), 711 /*initializer*/ undefined); 712 changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); 713 }); 714 } 715 { 716 const text = ` 717class A { 718 x() { 719 } 720} 721`; 722 runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 723 const newNode = factory.createPropertyDeclaration( 724 /*decorators*/ undefined, 725 /*modifiers*/ undefined, 726 factory.createComputedPropertyName(factory.createNumericLiteral(1)), 727 /*questionToken*/ undefined, 728 factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), 729 /*initializer*/ undefined); 730 changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); 731 }); 732 } 733 { 734 const text = ` 735interface A { 736 x 737} 738`; 739 runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 740 const newNode = factory.createPropertyDeclaration( 741 /*decorators*/ undefined, 742 /*modifiers*/ undefined, 743 factory.createComputedPropertyName(factory.createNumericLiteral(1)), 744 /*questionToken*/ undefined, 745 factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), 746 /*initializer*/ undefined); 747 changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); 748 }); 749 } 750 { 751 const text = ` 752interface A { 753 x() 754} 755`; 756 runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 757 const newNode = factory.createPropertyDeclaration( 758 /*decorators*/ undefined, 759 /*modifiers*/ undefined, 760 factory.createComputedPropertyName(factory.createNumericLiteral(1)), 761 /*questionToken*/ undefined, 762 factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), 763 /*initializer*/ undefined); 764 changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); 765 }); 766 } 767 { 768 const text = ` 769let x = foo 770`; 771 runSingleFileTest("insertNodeInStatementListAfterNodeWithoutSeparator1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { 772 const newNode = factory.createExpressionStatement(factory.createParenthesizedExpression(factory.createNumericLiteral(1))); 773 changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), newNode); 774 }); 775 } 776 }); 777} 778