1namespace ts.textStorage { 2 describe("unittests:: tsserver:: Text storage", () => { 3 const f = { 4 path: "/a/app.ts", 5 content: ` 6 let x = 1; 7 let y = 2; 8 function bar(a: number) { 9 return a + 1; 10 }` 11 }; 12 13 function getDummyScriptInfo(fileName: string) { 14 return { fileName, closeSourceMapFileWatcher: noop } as server.ScriptInfo; 15 } 16 17 it("text based storage should be have exactly the same as script version cache", () => { 18 19 const host = projectSystem.createServerHost([f]); 20 // Since script info is not used in these tests, just cheat by passing undefined 21 const ts1 = new server.TextStorage(host, getDummyScriptInfo(server.asNormalizedPath(f.path))); 22 const ts2 = new server.TextStorage(host, getDummyScriptInfo(server.asNormalizedPath(f.path))); 23 24 ts1.useScriptVersionCache_TestOnly(); 25 ts2.useText(); 26 27 const lineMap = computeLineStarts(f.content); 28 29 for (let line = 0; line < lineMap.length; line++) { 30 const start = lineMap[line]; 31 const end = line === lineMap.length - 1 ? f.path.length : lineMap[line + 1]; 32 33 for (let offset = 0; offset < end - start; offset++) { 34 const pos1 = ts1.lineOffsetToPosition(line + 1, offset + 1); 35 const pos2 = ts2.lineOffsetToPosition(line + 1, offset + 1); 36 assert.strictEqual(pos1, pos2, `lineOffsetToPosition ${line + 1}-${offset + 1}: expected ${pos1} to equal ${pos2}`); 37 } 38 39 const {start: start1, length: length1 } = ts1.lineToTextSpan(line); 40 const {start: start2, length: length2 } = ts2.lineToTextSpan(line); 41 assert.strictEqual(start1, start2, `lineToTextSpan ${line}::start:: expected ${start1} to equal ${start2}`); 42 assert.strictEqual(length1, length2, `lineToTextSpan ${line}::length:: expected ${length1} to equal ${length2}`); 43 } 44 45 for (let pos = 0; pos < f.content.length; pos++) { 46 const { line: line1, offset: offset1 } = ts1.positionToLineOffset(pos); 47 const { line: line2, offset: offset2 } = ts2.positionToLineOffset(pos); 48 assert.strictEqual(line1, line2, `positionToLineOffset ${pos}::line:: expected ${line1} to equal ${line2}`); 49 assert.strictEqual(offset1, offset2, `positionToLineOffset ${pos}::offset:: expected ${offset1} to equal ${offset2}`); 50 } 51 }); 52 53 it("should switch to script version cache if necessary", () => { 54 const host = projectSystem.createServerHost([f]); 55 // Since script info is not used in these tests, just cheat by passing undefined 56 const ts1 = new server.TextStorage(host, getDummyScriptInfo(server.asNormalizedPath(f.path))); 57 58 ts1.getSnapshot(); 59 assert.isFalse(ts1.hasScriptVersionCache_TestOnly(), "should not have script version cache - 1"); 60 61 ts1.edit(0, 5, " "); 62 assert.isTrue(ts1.hasScriptVersionCache_TestOnly(), "have script version cache - 1"); 63 64 ts1.useText(); 65 assert.isFalse(ts1.hasScriptVersionCache_TestOnly(), "should not have script version cache - 2"); 66 67 ts1.getAbsolutePositionAndLineText(0); 68 assert.isTrue(ts1.hasScriptVersionCache_TestOnly(), "have script version cache - 2"); 69 }); 70 71 it("should be able to return the file size immediately after construction", () => { 72 const host = projectSystem.createServerHost([f]); 73 // Since script info is not used in these tests, just cheat by passing undefined 74 const ts1 = new server.TextStorage(host, getDummyScriptInfo(server.asNormalizedPath(f.path))); 75 76 assert.strictEqual(f.content.length, ts1.getTelemetryFileSize()); 77 }); 78 79 it("should be able to return the file size when backed by text", () => { 80 const host = projectSystem.createServerHost([f]); 81 // Since script info is not used in these tests, just cheat by passing undefined 82 const ts1 = new server.TextStorage(host, getDummyScriptInfo(server.asNormalizedPath(f.path))); 83 84 ts1.useText(f.content); 85 assert.isFalse(ts1.hasScriptVersionCache_TestOnly()); 86 87 assert.strictEqual(f.content.length, ts1.getTelemetryFileSize()); 88 }); 89 90 it("should be able to return the file size when backed by a script version cache", () => { 91 const host = projectSystem.createServerHost([f]); 92 // Since script info is not used in these tests, just cheat by passing undefined 93 const ts1 = new server.TextStorage(host, getDummyScriptInfo(server.asNormalizedPath(f.path))); 94 95 ts1.useScriptVersionCache_TestOnly(); 96 assert.isTrue(ts1.hasScriptVersionCache_TestOnly()); 97 98 assert.strictEqual(f.content.length, ts1.getTelemetryFileSize()); 99 }); 100 101 it("should be able to return the file size when a JS file is too large to load into text", () => { 102 const largeFile = { 103 path: "/a/large.js", 104 content: " ".repeat(server.maxFileSize + 1) 105 }; 106 107 const host = projectSystem.createServerHost([largeFile]); 108 109 // The large-file handling requires a ScriptInfo with a containing project 110 const projectService = projectSystem.createProjectService(host); 111 projectService.openClientFile(largeFile.path); 112 const scriptInfo = projectService.getScriptInfo(largeFile.path); 113 114 const ts1 = new server.TextStorage(host, scriptInfo!); 115 116 assert.isTrue(ts1.reloadFromDisk()); 117 assert.isFalse(ts1.hasScriptVersionCache_TestOnly()); 118 119 assert.strictEqual(largeFile.content.length, ts1.getTelemetryFileSize()); 120 }); 121 122 it("should return the file size without reloading the file", () => { 123 const oldText = "hello"; 124 const newText = "goodbye"; 125 126 const changingFile = { 127 path: "/a/changing.ts", 128 content: oldText 129 }; 130 131 const host = projectSystem.createServerHost([changingFile]); 132 // Since script info is not used in these tests, just cheat by passing undefined 133 const ts1 = new server.TextStorage(host, getDummyScriptInfo(server.asNormalizedPath(changingFile.path))); 134 135 assert.isTrue(ts1.reloadFromDisk()); 136 137 // Refresh the file and notify TextStorage 138 host.writeFile(changingFile.path, newText); 139 ts1.delayReloadFromFileIntoText(); 140 141 assert.strictEqual(oldText.length, ts1.getTelemetryFileSize()); 142 143 assert.isTrue(ts1.reloadWithFileText()); 144 145 assert.strictEqual(newText.length, ts1.getTelemetryFileSize()); 146 }); 147 }); 148} 149