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