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 assert(result.targetRange === undefined, "failure expected"); 12 const sortedErrors = result.errors!.map(e => <string>e.messageText).sort(); 13 assert.deepEqual(sortedErrors, expectedErrors.sort(), "unexpected errors"); 14 }); 15 } 16 17 function testExtractRange(s: string): void { 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 describe("unittests:: services:: extract:: extractRanges", () => { 46 it("get extract range from selection", () => { 47 testExtractRange(` 48 [#| 49 [$|var x = 1; 50 var y = 2;|]|] 51 `); 52 testExtractRange(` 53 [#| 54 var x = 1; 55 var y = 2|]; 56 `); 57 testExtractRange(` 58 [#|var x = 1|]; 59 var y = 2; 60 `); 61 testExtractRange(` 62 if ([#|[#extracted|a && b && c && d|]|]) { 63 } 64 `); 65 testExtractRange(` 66 if [#|(a && b && c && d|]) { 67 } 68 `); 69 testExtractRange(` 70 if (a && b && c && d) { 71 [#| [$|var x = 1; 72 console.log(x);|] |] 73 } 74 `); 75 testExtractRange(` 76 [#| 77 if (a) { 78 return 100; 79 } |] 80 `); 81 testExtractRange(` 82 function foo() { 83 [#| [$|if (a) { 84 } 85 return 100|] |] 86 } 87 `); 88 testExtractRange(` 89 [#| 90 [$|l1: 91 if (x) { 92 break l1; 93 }|]|] 94 `); 95 testExtractRange(` 96 [#| 97 [$|l2: 98 { 99 if (x) { 100 } 101 break l2; 102 }|]|] 103 `); 104 testExtractRange(` 105 while (true) { 106 [#| if(x) { 107 } 108 break; |] 109 } 110 `); 111 testExtractRange(` 112 while (true) { 113 [#| if(x) { 114 } 115 continue; |] 116 } 117 `); 118 testExtractRange(` 119 l3: 120 { 121 [#| 122 if (x) { 123 } 124 break l3; |] 125 } 126 `); 127 testExtractRange(` 128 function f() { 129 while (true) { 130 [#| 131 if (x) { 132 return; 133 } |] 134 } 135 } 136 `); 137 testExtractRange(` 138 function f() { 139 while (true) { 140 [#| 141 [$|if (x) { 142 } 143 return;|] 144 |] 145 } 146 } 147 `); 148 testExtractRange(` 149 function f() { 150 return [#| [$|1 + 2|] |]+ 3; 151 } 152 } 153 `); 154 testExtractRange(` 155 function f(x: number) { 156 [#|[$|try { 157 x++; 158 } 159 finally { 160 return 1; 161 }|]|] 162 } 163 `); 164 165 // Variable statements 166 testExtractRange(`[#|let x = [$|1|];|]`); 167 testExtractRange(`[#|let x = [$|1|], y;|]`); 168 testExtractRange(`[#|[$|let x = 1, y = 1;|]|]`); 169 170 // Variable declarations 171 testExtractRange(`let [#|x = [$|1|]|];`); 172 testExtractRange(`let [#|x = [$|1|]|], y = 2;`); 173 testExtractRange(`let x = 1, [#|y = [$|2|]|];`); 174 175 // Return statements 176 testExtractRange(`[#|return [$|1|];|]`); 177 }); 178 179 testExtractRangeFailed("extractRangeFailed1", 180 ` 181namespace A { 182function f() { 183 [#| 184 let x = 1 185 if (x) { 186 return 10; 187 } 188 |] 189} 190} 191 `, 192 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalReturnStatement.message]); 193 194 testExtractRangeFailed("extractRangeFailed2", 195 ` 196namespace A { 197function f() { 198 while (true) { 199 [#| 200 let x = 1 201 if (x) { 202 break; 203 } 204 |] 205 } 206} 207} 208 `, 209 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); 210 211 testExtractRangeFailed("extractRangeFailed3", 212 ` 213namespace A { 214function f() { 215 while (true) { 216 [#| 217 let x = 1 218 if (x) { 219 continue; 220 } 221 |] 222 } 223} 224} 225 `, 226 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); 227 228 testExtractRangeFailed("extractRangeFailed4", 229 ` 230namespace A { 231function f() { 232 l1: { 233 [#| 234 let x = 1 235 if (x) { 236 break l1; 237 } 238 |] 239 } 240} 241} 242 `, 243 [refactor.extractSymbol.Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange.message]); 244 245 testExtractRangeFailed("extractRangeFailed5", 246 ` 247namespace A { 248function f() { 249 [#| 250 try { 251 f2() 252 return 10; 253 } 254 catch (e) { 255 } 256 |] 257} 258function f2() { 259} 260} 261 `, 262 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalReturnStatement.message]); 263 264 testExtractRangeFailed("extractRangeFailed6", 265 ` 266namespace A { 267function f() { 268 [#| 269 try { 270 f2() 271 } 272 catch (e) { 273 return 10; 274 } 275 |] 276} 277function f2() { 278} 279} 280 `, 281 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalReturnStatement.message]); 282 283 testExtractRangeFailed("extractRangeFailed7", 284 ` 285function test(x: number) { 286while (x) { 287 x--; 288 [#|break;|] 289} 290} 291 `, 292 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); 293 294 testExtractRangeFailed("extractRangeFailed8", 295 ` 296function test(x: number) { 297switch (x) { 298 case 1: 299 [#|break;|] 300} 301} 302 `, 303 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); 304 305 testExtractRangeFailed("extractRangeFailed9", 306 `var x = ([#||]1 + 2);`, 307 [refactor.extractSymbol.Messages.cannotExtractEmpty.message]); 308 309 testExtractRangeFailed("extractRangeFailed10", 310 ` 311 function f() { 312 return 1 + [#|2 + 3|]; 313 } 314 } 315 `, 316 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 317 318 testExtractRangeFailed("extractRangeFailed11", 319 ` 320 function f(x: number) { 321 while (true) { 322 [#|try { 323 x++; 324 } 325 finally { 326 break; 327 }|] 328 } 329 } 330 `, 331 [refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); 332 333 testExtractRangeFailed("extractRangeFailed12", 334 `let [#|x|];`, 335 [refactor.extractSymbol.Messages.statementOrExpressionExpected.message]); 336 337 testExtractRangeFailed("extractRangeFailed13", 338 `[#|return;|]`, 339 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 340 341 testExtractRangeFailed("extractRangeFailed14", 342 ` 343 switch(1) { 344 case [#|1: 345 break;|] 346 } 347 `, 348 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 349 350 testExtractRangeFailed("extractRangeFailed15", 351 ` 352 switch(1) { 353 case [#|1: 354 break|]; 355 } 356 `, 357 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 358 359 // Documentation only - it would be nice if the result were [$|1|] 360 testExtractRangeFailed("extractRangeFailed16", 361 ` 362 switch(1) { 363 [#|case 1|]: 364 break; 365 } 366 `, 367 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 368 369 // Documentation only - it would be nice if the result were [$|1|] 370 testExtractRangeFailed("extractRangeFailed17", 371 ` 372 switch(1) { 373 [#|case 1:|] 374 break; 375 } 376 `, 377 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 378 379 testExtractRangeFailed("extractRangeFailed18", 380 `[#|{ 1;|] }`, 381 [refactor.extractSymbol.Messages.cannotExtractRange.message]); 382 383 testExtractRangeFailed("extractRangeFailed19", 384 `[#|/** @type {number} */|] const foo = 1;`, 385 [refactor.extractSymbol.Messages.cannotExtractJSDoc.message]); 386 387 testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, [refactor.extractSymbol.Messages.cannotExtractIdentifier.message]); 388 }); 389} 390