1namespace ts.projectSystem { 2 describe("unittests:: tsserver:: navigate-to for javascript project", () => { 3 function findNavToItem(items: protocol.NavtoItem[], itemName: string, itemKind: string) { 4 return find(items, item => item.name === itemName && item.kind === itemKind); 5 } 6 7 function containsNavToItem(items: protocol.NavtoItem[], itemName: string, itemKind: string) { 8 return findNavToItem(items, itemName, itemKind) !== undefined; 9 } 10 11 it("should not include type symbols", () => { 12 const file1: File = { 13 path: "/a/b/file1.js", 14 content: "function foo() {}" 15 }; 16 const configFile: File = { 17 path: "/a/b/jsconfig.json", 18 content: "{}" 19 }; 20 const host = createServerHost([file1, configFile, libFile]); 21 const session = createSession(host); 22 openFilesForSession([file1], session); 23 24 // Try to find some interface type defined in lib.d.ts 25 const libTypeNavToRequest = makeSessionRequest<protocol.NavtoRequestArgs>(CommandNames.Navto, { searchValue: "Document", file: file1.path, projectFileName: configFile.path }); 26 const items = session.executeCommand(libTypeNavToRequest).response as protocol.NavtoItem[]; 27 assert.isFalse(containsNavToItem(items, "Document", "interface"), `Found lib.d.ts symbol in JavaScript project nav to request result.`); 28 29 const localFunctionNavToRequst = makeSessionRequest<protocol.NavtoRequestArgs>(CommandNames.Navto, { searchValue: "foo", file: file1.path, projectFileName: configFile.path }); 30 const items2 = session.executeCommand(localFunctionNavToRequst).response as protocol.NavtoItem[]; 31 assert.isTrue(containsNavToItem(items2, "foo", "function"), `Cannot find function symbol "foo".`); 32 }); 33 34 it("should de-duplicate symbols", () => { 35 const configFile1: File = { 36 path: "/a/tsconfig.json", 37 content: `{ 38 "compilerOptions": { 39 "composite": true 40 } 41}` 42 }; 43 const file1: File = { 44 path: "/a/index.ts", 45 content: "export const abcdef = 1;" 46 }; 47 const configFile2: File = { 48 path: "/b/tsconfig.json", 49 content: `{ 50 "compilerOptions": { 51 "composite": true 52 }, 53 "references": [ 54 { "path": "../a" } 55 ] 56}` 57 }; 58 const file2: File = { 59 path: "/b/index.ts", 60 content: `import a = require("../a"); 61export const ghijkl = a.abcdef;` 62 }; 63 const host = createServerHost([configFile1, file1, configFile2, file2]); 64 const logger = createHasErrorMessageLogger().logger; 65 const logs: string[] = []; 66 logger.info = s => logs.push(s); 67 const session = createSession(host, { logger }); 68 openFilesForSession([file1, file2], session); 69 logs.length = 0; 70 71 const request = makeSessionRequest<protocol.NavtoRequestArgs>(CommandNames.Navto, { searchValue: "abcdef", file: file1.path }); 72 const items = session.executeCommand(request).response as protocol.NavtoItem[]; 73 assert.strictEqual(items.length, 1); 74 const item = items[0]; 75 assert.strictEqual(item.name, "abcdef"); 76 assert.strictEqual(item.file, file1.path); 77 assert.deepEqual(logs, []); 78 }); 79 80 it("should de-duplicate symbols when searching all projects", () => { 81 const solutionConfig: File = { 82 path: "/tsconfig.json", 83 content: JSON.stringify({ 84 references: [{ path: "./a" }, { path: "./b" }], 85 files: [], 86 }) 87 }; 88 const configFile1: File = { 89 path: "/a/tsconfig.json", 90 content: `{ 91 "compilerOptions": { 92 "composite": true 93 } 94}` 95 }; 96 const file1: File = { 97 path: "/a/index.ts", 98 content: "export const abcdef = 1;" 99 }; 100 const configFile2: File = { 101 path: "/b/tsconfig.json", 102 content: `{ 103 "compilerOptions": { 104 "composite": true 105 }, 106 "references": [ 107 { "path": "../a" } 108 ] 109}` 110 }; 111 const file2: File = { 112 path: "/b/index.ts", 113 content: `import a = require("../a"); 114export const ghijkl = a.abcdef;` 115 }; 116 const host = createServerHost([configFile1, file1, configFile2, file2, solutionConfig]); 117 const logger = createHasErrorMessageLogger().logger; 118 const logs: string[] = []; 119 logger.info = s => logs.push(s); 120 const session = createSession(host, { logger }); 121 openFilesForSession([file1], session); 122 logs.length = 0; 123 124 const request = makeSessionRequest<protocol.NavtoRequestArgs>(CommandNames.Navto, { searchValue: "abcdef" }); 125 const items = session.executeCommand(request).response as protocol.NavtoItem[]; 126 assert.strictEqual(items.length, 1); 127 const item = items[0]; 128 assert.strictEqual(item.name, "abcdef"); 129 assert.strictEqual(item.file, file1.path); 130 // Cannt check logs as empty since it loads projects and writes information for those in the log 131 assert.isFalse(contains(logs, "Search path: /a")); 132 assert.isFalse(contains(logs, "For info: /a/index.ts :: Config file name: /a/tsconfig.json")); 133 }); 134 135 it("should work with Deprecated", () => { 136 const file1: File = { 137 path: "/a/b/file1.js", 138 content: "/** @deprecated */\nfunction foo () {}" 139 }; 140 const configFile: File = { 141 path: "/a/b/jsconfig.json", 142 content: "{}" 143 }; 144 const host = createServerHost([file1, configFile, libFile]); 145 const session = createSession(host); 146 openFilesForSession([file1], session); 147 148 // Try to find some interface type defined in lib.d.ts 149 const libTypeNavToRequest = makeSessionRequest<protocol.NavtoRequestArgs>(CommandNames.Navto, { searchValue: "foo", file: file1.path, projectFileName: configFile.path }); 150 const items = session.executeCommand(libTypeNavToRequest).response as protocol.NavtoItem[]; 151 const fooItem = findNavToItem(items, "foo", "function"); 152 assert.isNotNull(fooItem, `Cannot find function symbol "foo".`); 153 assert.isTrue(fooItem?.kindModifiers?.includes("deprecated")); 154 }); 155 }); 156} 157