• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1namespace ts.projectSystem {
2    describe("unittests:: tsserver:: rename", () => {
3        it("works with fileToRename", () => {
4            const aTs: File = { path: "/a.ts", content: "export const a = 0;" };
5            const bTs: File = { path: "/b.ts", content: 'import { a } from "./a";' };
6
7            const session = createSession(createServerHost([aTs, bTs]));
8            openFilesForSession([bTs], session);
9
10            // rename fails with allowRenameOfImportPath disabled
11            const response1 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, 'a";'));
12            assert.deepEqual<protocol.RenameResponseBody | undefined>(response1, {
13                info: {
14                    canRename: false,
15                    localizedErrorMessage: "You cannot rename this element."
16                },
17                locs: [],
18            });
19
20            // rename succeeds with allowRenameOfImportPath enabled in host
21            session.getProjectService().setHostConfiguration({ preferences: { allowRenameOfImportPath: true } });
22            const response2 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, 'a";'));
23            assert.deepEqual<protocol.RenameResponseBody | undefined>(response2, {
24                info: {
25                    canRename: true,
26                    fileToRename: aTs.path,
27                    displayName: aTs.path,
28                    fullDisplayName: aTs.path,
29                    kind: ScriptElementKind.moduleElement,
30                    kindModifiers: "",
31                    triggerSpan: protocolTextSpanFromSubstring(bTs.content, "a", { index: 1 }),
32                },
33                locs: [{
34                    file: bTs.path,
35                    locs: [
36                        protocolRenameSpanFromSubstring({
37                            fileText: bTs.content,
38                            text: "./a",
39                            contextText: bTs.content
40                        })
41                    ]
42                }],
43            });
44
45            // rename succeeds with allowRenameOfImportPath enabled in file
46            session.getProjectService().setHostConfiguration({ preferences: { allowRenameOfImportPath: false } });
47            session.getProjectService().setHostConfiguration({ file: "/b.ts", formatOptions: {}, preferences: { allowRenameOfImportPath: true } });
48            const response3 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, 'a";'));
49            assert.deepEqual<protocol.RenameResponseBody | undefined>(response3, {
50                info: {
51                    canRename: true,
52                    fileToRename: aTs.path,
53                    displayName: aTs.path,
54                    fullDisplayName: aTs.path,
55                    kind: ScriptElementKind.moduleElement,
56                    kindModifiers: "",
57                    triggerSpan: protocolTextSpanFromSubstring(bTs.content, "a", { index: 1 }),
58                },
59                locs: [{
60                    file: bTs.path,
61                    locs: [
62                        protocolRenameSpanFromSubstring({
63                            fileText: bTs.content,
64                            text: "./a",
65                            contextText: bTs.content
66                        })
67                    ]
68                }],
69            });
70        });
71
72        it("works with prefixText and suffixText when enabled", () => {
73            const aTs: File = { path: "/a.ts", content: "const x = 0; const o = { x };" };
74            const host = createServerHost([aTs]);
75            const session = createSession(host);
76            openFilesForSession([aTs], session);
77
78            // rename with prefixText and suffixText disabled
79            const response1 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "x"));
80            assert.deepEqual<protocol.RenameResponseBody | undefined>(response1, {
81                info: {
82                    canRename: true,
83                    fileToRename: undefined,
84                    displayName: "x",
85                    fullDisplayName: "x",
86                    kind: ScriptElementKind.constElement,
87                    kindModifiers: ScriptElementKindModifier.none,
88                    triggerSpan: protocolTextSpanFromSubstring(aTs.content, "x"),
89                },
90                locs: [
91                    {
92                        file: aTs.path,
93                        locs: [
94                            protocolRenameSpanFromSubstring({
95                                fileText: aTs.content,
96                                text: "x",
97                                contextText: "const x = 0;"
98                            }),
99                            protocolRenameSpanFromSubstring({
100                                fileText: aTs.content,
101                                text: "x",
102                                options: { index: 1 }
103                            }),
104                        ],
105                    },
106                ],
107            });
108
109            // rename with prefixText and suffixText enabled in host
110            session.getProjectService().setHostConfiguration({ preferences: { providePrefixAndSuffixTextForRename: true } });
111            const response2 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "x"));
112            assert.deepEqual<protocol.RenameResponseBody | undefined>(response2, {
113                info: {
114                    canRename: true,
115                    fileToRename: undefined,
116                    displayName: "x",
117                    fullDisplayName: "x",
118                    kind: ScriptElementKind.constElement,
119                    kindModifiers: ScriptElementKindModifier.none,
120                    triggerSpan: protocolTextSpanFromSubstring(aTs.content, "x"),
121                },
122                locs: [
123                    {
124                        file: aTs.path,
125                        locs: [
126                            protocolRenameSpanFromSubstring({
127                                fileText: aTs.content,
128                                text: "x",
129                                contextText: "const x = 0;"
130                            }),
131                            protocolRenameSpanFromSubstring({
132                                fileText: aTs.content,
133                                text: "x",
134                                options: { index: 1 },
135                                prefixSuffixText: { prefixText: "x: " }
136                            }),
137                        ],
138                    },
139                ],
140            });
141
142            // rename with prefixText and suffixText enabled for file
143            session.getProjectService().setHostConfiguration({ preferences: { providePrefixAndSuffixTextForRename: false } });
144            session.getProjectService().setHostConfiguration({ file: "/a.ts", formatOptions: {}, preferences: { providePrefixAndSuffixTextForRename: true } });
145            const response3 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "x"));
146            assert.deepEqual<protocol.RenameResponseBody | undefined>(response3, {
147                info: {
148                    canRename: true,
149                    fileToRename: undefined,
150                    displayName: "x",
151                    fullDisplayName: "x",
152                    kind: ScriptElementKind.constElement,
153                    kindModifiers: ScriptElementKindModifier.none,
154                    triggerSpan: protocolTextSpanFromSubstring(aTs.content, "x"),
155                },
156                locs: [
157                    {
158                        file: aTs.path,
159                        locs: [
160                            protocolRenameSpanFromSubstring({
161                                fileText: aTs.content,
162                                text: "x",
163                                contextText: "const x = 0;"
164                            }),
165                            protocolRenameSpanFromSubstring({
166                                fileText: aTs.content,
167                                text: "x",
168                                options: { index: 1 },
169                                prefixSuffixText: { prefixText: "x: " }
170                            }),
171                        ],
172                    },
173                ],
174            });
175        });
176
177        it("export default anonymous function works with prefixText and suffixText when disabled", () => {
178            const aTs: File = { path: "/a.ts", content: "export default function() {}" };
179            const bTs: File = { path: "/b.ts", content: `import aTest from "./a"; function test() { return aTest(); }` };
180
181            const session = createSession(createServerHost([aTs, bTs]));
182            openFilesForSession([bTs], session);
183
184            session.getProjectService().setHostConfiguration({ preferences: { providePrefixAndSuffixTextForRename: false } });
185            const response1 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, "aTest("));
186            assert.deepEqual<protocol.RenameResponseBody | undefined>(response1, {
187                info: {
188                    canRename: true,
189                    fileToRename: undefined,
190                    displayName: "aTest",
191                    fullDisplayName: "aTest",
192                    kind: ScriptElementKind.alias,
193                    kindModifiers: "export",
194                    triggerSpan: protocolTextSpanFromSubstring(bTs.content, "aTest", { index: 1 })
195                },
196                locs: [{
197                    file: bTs.path,
198                    locs: [
199                        protocolRenameSpanFromSubstring({
200                            fileText: bTs.content,
201                            text: "aTest",
202                            contextText: `import aTest from "./a";`
203                        }),
204                        protocolRenameSpanFromSubstring({
205                            fileText: bTs.content,
206                            text: "aTest",
207                            options: { index: 1 },
208                        })
209                    ]
210                }],
211            });
212        });
213
214        it("rename behavior is based on file of rename initiation", () => {
215            const aTs: File = { path: "/a.ts", content: "const x = 1; export { x };" };
216            const bTs: File = { path: "/b.ts", content: `import { x } from "./a"; const y = x + 1;` };
217            const host = createServerHost([aTs, bTs]);
218            const session = createSession(host);
219            openFilesForSession([aTs, bTs], session);
220
221            // rename from file with prefixText and suffixText enabled
222            session.getProjectService().setHostConfiguration({ file: "/a.ts", formatOptions: {}, preferences: { providePrefixAndSuffixTextForRename: true } });
223            const response1 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "x"));
224            assert.deepEqual<protocol.RenameResponseBody | undefined>(response1, {
225                info: {
226                    canRename: true,
227                    fileToRename: undefined,
228                    displayName: "x",
229                    fullDisplayName: "x",
230                    kind: ScriptElementKind.constElement,
231                    kindModifiers: ScriptElementKindModifier.none,
232                    triggerSpan: protocolTextSpanFromSubstring(aTs.content, "x"),
233                },
234                locs: [
235                    {
236                        file: aTs.path,
237                        locs: [
238                            protocolRenameSpanFromSubstring({
239                                fileText: aTs.content,
240                                text: "x",
241                                contextText: "const x = 1;"
242                            }),
243                            protocolRenameSpanFromSubstring({
244                                fileText: aTs.content,
245                                text: "x",
246                                options: { index: 2 },
247                                contextText: "export { x };",
248                                prefixSuffixText: { suffixText: " as x" }
249                            }),
250                        ],
251                    },
252                ],
253            });
254
255            // rename from file with prefixText and suffixText disabled
256            const response2 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, "x"));
257            assert.deepEqual<protocol.RenameResponseBody | undefined>(response2, {
258                info: {
259                    canRename: true,
260                    fileToRename: undefined,
261                    displayName: "x",
262                    fullDisplayName: "x",
263                    kind: ScriptElementKind.alias,
264                    kindModifiers: ScriptElementKindModifier.none,
265                    triggerSpan: protocolTextSpanFromSubstring(bTs.content, "x"),
266                },
267                locs: [
268                    {
269                        file: bTs.path,
270                        locs: [
271                            protocolRenameSpanFromSubstring({
272                                fileText: bTs.content,
273                                text: "x",
274                                contextText: `import { x } from "./a";`
275                            }),
276                            protocolRenameSpanFromSubstring({
277                                fileText: bTs.content,
278                                text: "x",
279                                options: { index: 1 },
280                            })
281                        ]
282                    },
283                    {
284                        file: aTs.path,
285                        locs: [
286                            protocolRenameSpanFromSubstring({
287                                fileText: aTs.content,
288                                text: "x",
289                                contextText: "const x = 1;"
290                            }),
291                            protocolRenameSpanFromSubstring({
292                                fileText: aTs.content,
293                                text: "x",
294                                options: { index: 2 },
295                                contextText: "export { x };",
296                            }),
297                        ],
298                    },
299                ],
300            });
301        });
302    });
303}
304