• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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