1namespace ts { 2 function testExtractRangeFailed(caption: string, s: string, expectedErrors: string[]) { 3 return it(caption, () => { 4 const t = extractTest(s); 5 const file = createSourceFile("a.ts", t.source, ScriptTarget.Latest, /*setParentNodes*/ true); 6 const selectionRange = t.ranges.get("selection"); 7 if (!selectionRange) { 8 throw new Error(`Test ${s} does not specify selection range`); 9 } 10 const result = refactor.extractSymbol.getRangeToExtract(file, createTextSpanFromRange(selectionRange), /*userRequested*/ false); 11 const sortedErrors = result.errors!.map(e => e.messageText as string).sort(); 12 assert.deepEqual(sortedErrors, expectedErrors.sort(), "unexpected errors"); 13 }); 14 } 15 16 function testExtractRange(caption: string, s: string) { 17 return it(caption, () => { 18 const t = extractTest(s); 19 const f = createSourceFile("a.ts", t.source, ScriptTarget.Latest, /*setParentNodes*/ true); 20 const selectionRange = t.ranges.get("selection"); 21 if (!selectionRange) { 22 throw new Error(`Test ${s} does not specify selection range`); 23 } 24 const result = refactor.extractSymbol.getRangeToExtract(f, createTextSpanFromRange(selectionRange)); 25 const expectedRange = t.ranges.get("extracted"); 26 if (expectedRange) { 27 let pos: number, end: number; 28 const targetRange = result.targetRange!; 29 if (isArray(targetRange.range)) { 30 pos = targetRange.range[0].getStart(f); 31 end = last(targetRange.range).getEnd(); 32 } 33 else { 34 pos = targetRange.range.getStart(f); 35 end = targetRange.range.getEnd(); 36 } 37 assert.equal(pos, expectedRange.pos, "incorrect pos of range"); 38 assert.equal(end, expectedRange.end, "incorrect end of range"); 39 } 40 else { 41 assert.isTrue(!result.targetRange, `expected range to extract to be undefined`); 42 } 43 }); 44 } 45 46 describe("unittests:: services:: extract:: extractRanges", () => { 47 describe("get extract range from selection", () => { 48 testExtractRange("extractRange1", ` 49 [#| 50 [$|var x = 1; 51 var y = 2;|]|] 52 `); 53 testExtractRange("extractRange2", ` 54 [$|[#|var x = 1; 55 var y = 2|];|] 56 `); 57 testExtractRange("extractRange3", ` 58 [#|var x = [$|1|]|]; 59 var y = 2; 60 `); 61 testExtractRange("extractRange4", ` 62 var x = [$|10[#|00|]|]; 63 `); 64 testExtractRange("extractRange5", ` 65 [$|va[#|r foo = 1; 66 var y = 200|]0;|] 67 `); 68 testExtractRange("extractRange6", ` 69 var x = [$|fo[#|o.bar.baz()|]|]; 70 `); 71 testExtractRange("extractRange7", ` 72 if ([#|[#extracted|a && b && c && d|]|]) { 73 } 74 `); 75 testExtractRange("extractRange8", ` 76 if [#|(a && b && c && d|]) { 77 } 78 `); 79 testExtractRange("extractRange9", ` 80 if ([$|a[#|a && b && c && d|]d|]) { 81 } 82 `); 83 testExtractRange("extractRange10", ` 84 if (a && b && c && d) { 85 [#| [$|var x = 1; 86 console.log(x);|] |] 87 } 88 `); 89 testExtractRange("extractRange11", ` 90 [#| 91 if (a) { 92 return 100; 93 } |] 94 `); 95 testExtractRange("extractRange12", ` 96 function foo() { 97 [#| [$|if (a) { 98 } 99 return 100|] |] 100 } 101 `); 102 testExtractRange("extractRange13", ` 103 [#| 104 [$|l1: 105 if (x) { 106 break l1; 107 }|]|] 108 `); 109 testExtractRange("extractRange14", ` 110 [#| 111 [$|l2: 112 { 113 if (x) { 114 } 115 break l2; 116 }|]|] 117 `); 118 testExtractRange("extractRange15", ` 119 while (true) { 120 [#| if(x) { 121 } 122 break; |] 123 } 124 `); 125 testExtractRange("extractRange16", ` 126 while (true) { 127 [#| if(x) { 128 } 129 continue; |] 130 } 131 `); 132 testExtractRange("extractRange17", ` 133 l3: 134 { 135 [#| 136 if (x) { 137 } 138 break l3; |] 139 } 140 `); 141 testExtractRange("extractRange18", ` 142 function f() { 143 while (true) { 144 [#| 145 if (x) { 146 return; 147 } |] 148 } 149 } 150 `); 151 testExtractRange("extractRange19", ` 152 function f() { 153 while (true) { 154 [#| 155 [$|if (x) { 156 } 157 return;|] 158 |] 159 } 160 } 161 `); 162 testExtractRange("extractRange20", ` 163 function f() { 164 return [#| [$|1 + 2|] |]+ 3; 165 } 166 } 167 `); 168 testExtractRange("extractRange21", ` 169 function f(x: number) { 170 [#|[$|try { 171 x++; 172 } 173 finally { 174 return 1; 175 }|]|] 176 } 177 `); 178 179 // Variable statements 180 testExtractRange("extractRange22", `[#|let x = [$|1|];|]`); 181 testExtractRange("extractRange23", `[#|let x = [$|1|], y;|]`); 182 testExtractRange("extractRange24", `[#|[$|let x = 1, y = 1;|]|]`); 183 184 // Variable declarations 185 testExtractRange("extractRange25", `let [#|x = [$|1|]|];`); 186 testExtractRange("extractRange26", `let [#|x = [$|1|]|], y = 2;`); 187 testExtractRange("extractRange27", `let x = 1, [#|y = [$|2|]|];`); 188 189 // Return statements 190 testExtractRange("extractRange28", `[#|return [$|1|];|]`); 191 192 // For statements 193 testExtractRange("extractRange29", `for ([#|var i = [$|1|]|]; i < 2; i++) {}`); 194 testExtractRange("extractRange30", `for (var i = [#|[$|1|]|]; i < 2; i++) {}`); 195 }); 196 197 testExtractRangeFailed("extractRangeFailed1", 198 ` 199namespace A { 200function f() { 201 [#| 202 let x = 1 203 if (x) { 204 return 10; 205 } 206 |] 207} 208} 209 `, 210 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalReturnStatement.message]); 211 212 testExtractRangeFailed("extractRangeFailed2", 213 ` 214namespace A { 215function f() { 216 while (true) { 217 [#| 218 let x = 1 219 if (x) { 220 break; 221 } 222 |] 223 } 224} 225} 226 `, 227 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); 228 229 testExtractRangeFailed("extractRangeFailed3", 230 ` 231namespace A { 232function f() { 233 while (true) { 234 [#| 235 let x = 1 236 if (x) { 237 continue; 238 } 239 |] 240 } 241} 242} 243 `, 244 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); 245 246 testExtractRangeFailed("extractRangeFailed4", 247 ` 248namespace A { 249function f() { 250 l1: { 251 [#| 252 let x = 1 253 if (x) { 254 break l1; 255 } 256 |] 257 } 258} 259} 260 `, 261 [refactor.extractSymbol.Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange.message]); 262 263 testExtractRangeFailed("extractRangeFailed5", 264 ` 265namespace A { 266function f() { 267 [#| 268 try { 269 f2() 270 return 10; 271 } 272 catch (e) { 273 } 274 |] 275} 276function f2() { 277} 278} 279 `, 280 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalReturnStatement.message]); 281 282 testExtractRangeFailed("extractRangeFailed6", 283 ` 284namespace A { 285function f() { 286 [#| 287 try { 288 f2() 289 } 290 catch (e) { 291 return 10; 292 } 293 |] 294} 295function f2() { 296} 297} 298 `, 299 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalReturnStatement.message]); 300 301 testExtractRangeFailed("extractRangeFailed7", 302 ` 303function test(x: number) { 304while (x) { 305 x--; 306 [#|break;|] 307} 308} 309 `, 310 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); 311 312 testExtractRangeFailed("extractRangeFailed8", 313 ` 314function test(x: number) { 315switch (x) { 316 case 1: 317 [#|break;|] 318} 319} 320 `, 321 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); 322 323 testExtractRangeFailed("extractRangeFailed9", 324 `var x = ([#||]1 + 2);`, 325 [refactor.extractSymbol.Messages.cannotExtractEmpty.message]); 326 327 testExtractRangeFailed("extractRangeFailed10", 328 ` 329 function f() { 330 return 1 + [#|2 + 3|]; 331 } 332 } 333 `, 334 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 335 336 testExtractRangeFailed("extractRangeFailed11", 337 ` 338 function f(x: number) { 339 while (true) { 340 [#|try { 341 x++; 342 } 343 finally { 344 break; 345 }|] 346 } 347 } 348 `, 349 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); 350 351 testExtractRangeFailed("extractRangeFailed12", 352 `let [#|x|];`, 353 [refactor.extractSymbol.Messages.statementOrExpressionExpected.message]); 354 355 testExtractRangeFailed("extractRangeFailed13", 356 `[#|return;|]`, 357 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 358 359 testExtractRangeFailed("extractRangeFailed14", 360 ` 361 switch(1) { 362 case [#|1: 363 break;|] 364 } 365 `, 366 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 367 368 testExtractRangeFailed("extractRangeFailed15", 369 ` 370 switch(1) { 371 case [#|1: 372 break|]; 373 } 374 `, 375 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 376 377 // Documentation only - it would be nice if the result were [$|1|] 378 testExtractRangeFailed("extractRangeFailed16", 379 ` 380 switch(1) { 381 [#|case 1|]: 382 break; 383 } 384 `, 385 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 386 387 // Documentation only - it would be nice if the result were [$|1|] 388 testExtractRangeFailed("extractRangeFailed17", 389 ` 390 switch(1) { 391 [#|case 1:|] 392 break; 393 } 394 `, 395 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 396 397 testExtractRangeFailed("extractRangeFailed18", 398 `[#|{ 1;|] }`, 399 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 400 401 testExtractRangeFailed("extractRangeFailed19", 402 `[#|/** @type {number} */|] const foo = 1;`, 403 [refactor.extractSymbol.Messages.cannotExtractJSDoc.message]); 404 405 testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, [refactor.extractSymbol.Messages.cannotExtractIdentifier.message]); 406 }); 407} 408