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