1namespace ts.projectSystem { 2 describe("unittests:: tsserver:: document registry in project service", () => { 3 const importModuleContent = `import {a} from "./module1"`; 4 const file: File = { 5 path: `${tscWatch.projectRoot}/index.ts`, 6 content: importModuleContent 7 }; 8 const moduleFile: File = { 9 path: `${tscWatch.projectRoot}/module1.d.ts`, 10 content: "export const a: number;" 11 }; 12 const configFile: File = { 13 path: `${tscWatch.projectRoot}/tsconfig.json`, 14 content: JSON.stringify({ files: ["index.ts"] }) 15 }; 16 17 function getProject(service: TestProjectService) { 18 return service.configuredProjects.get(configFile.path)!; 19 } 20 21 function checkProject(service: TestProjectService, moduleIsOrphan: boolean) { 22 // Update the project 23 const project = getProject(service); 24 project.getLanguageService(); 25 checkProjectActualFiles(project, [file.path, libFile.path, configFile.path, ...(moduleIsOrphan ? [] : [moduleFile.path])]); 26 const moduleInfo = service.getScriptInfo(moduleFile.path)!; 27 assert.isDefined(moduleInfo); 28 assert.equal(moduleInfo.isOrphan(), moduleIsOrphan); 29 const key = service.documentRegistry.getKeyForCompilationSettings(project.getCompilationSettings()); 30 assert.deepEqual(service.documentRegistry.getLanguageServiceRefCounts(moduleInfo.path, moduleInfo.scriptKind), [[key, moduleIsOrphan ? undefined : 1]]); 31 } 32 33 function createServiceAndHost() { 34 const host = createServerHost([file, moduleFile, libFile, configFile]); 35 const service = createProjectService(host); 36 service.openClientFile(file.path); 37 checkProject(service, /*moduleIsOrphan*/ false); 38 return { host, service }; 39 } 40 41 function changeFileToNotImportModule(service: TestProjectService) { 42 const info = service.getScriptInfo(file.path)!; 43 service.applyChangesToFile(info, singleIterator({ span: { start: 0, length: importModuleContent.length }, newText: "" })); 44 checkProject(service, /*moduleIsOrphan*/ true); 45 } 46 47 function changeFileToImportModule(service: TestProjectService) { 48 const info = service.getScriptInfo(file.path)!; 49 service.applyChangesToFile(info, singleIterator({ span: { start: 0, length: 0 }, newText: importModuleContent })); 50 checkProject(service, /*moduleIsOrphan*/ false); 51 } 52 53 it("Caches the source file if script info is orphan", () => { 54 const { service } = createServiceAndHost(); 55 const project = getProject(service); 56 57 const moduleInfo = service.getScriptInfo(moduleFile.path)!; 58 const sourceFile = moduleInfo.cacheSourceFile!.sourceFile; 59 assert.equal(project.getSourceFile(moduleInfo.path), sourceFile); 60 61 // edit file 62 changeFileToNotImportModule(service); 63 assert.equal(moduleInfo.cacheSourceFile!.sourceFile, sourceFile); 64 65 // write content back 66 changeFileToImportModule(service); 67 assert.equal(moduleInfo.cacheSourceFile!.sourceFile, sourceFile); 68 assert.equal(project.getSourceFile(moduleInfo.path), sourceFile); 69 }); 70 71 it("Caches the source file if script info is orphan, and orphan script info changes", () => { 72 const { host, service } = createServiceAndHost(); 73 const project = getProject(service); 74 75 const moduleInfo = service.getScriptInfo(moduleFile.path)!; 76 const sourceFile = moduleInfo.cacheSourceFile!.sourceFile; 77 assert.equal(project.getSourceFile(moduleInfo.path), sourceFile); 78 79 // edit file 80 changeFileToNotImportModule(service); 81 assert.equal(moduleInfo.cacheSourceFile!.sourceFile, sourceFile); 82 83 const updatedModuleContent = moduleFile.content + "\nexport const b: number;"; 84 host.writeFile(moduleFile.path, updatedModuleContent); 85 86 // write content back 87 changeFileToImportModule(service); 88 assert.notEqual(moduleInfo.cacheSourceFile!.sourceFile, sourceFile); 89 assert.equal(project.getSourceFile(moduleInfo.path), moduleInfo.cacheSourceFile!.sourceFile); 90 assert.equal(moduleInfo.cacheSourceFile!.sourceFile.text, updatedModuleContent); 91 }); 92 }); 93} 94