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