Last active
September 24, 2021 22:22
-
-
Save mizchi/b801edd949d9c6276a85eaffefe32b58 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ts from "typescript"; | |
type Files = { [key: string]: string }; | |
type SourceFiles = { [key: string]: ts.SourceFile | undefined }; | |
function getDiagnostics(rawFiles: Files, root: string[]) { | |
const compiledFiles: SourceFiles = {}; | |
const options: ts.CompilerOptions = { | |
target: ts.ScriptTarget.ESNext, | |
}; | |
const host: ts.CompilerHost = { | |
fileExists: (filePath) => !!rawFiles[filePath], | |
directoryExists: (dirPath) => dirPath === "/", | |
getCurrentDirectory: () => "/", | |
getDirectories: () => [], | |
getCanonicalFileName: (fileName) => fileName, | |
getNewLine: () => "\n", | |
getDefaultLibFileName: () => { | |
return "/_libs/lib.esnext.d.ts"; | |
}, | |
getSourceFile: (filePath) => { | |
// compile on demand | |
const compiled = compiledFiles[filePath]; | |
if (compiled) return compiled; | |
compiledFiles[filePath] = ts.createSourceFile( | |
filePath, | |
rawFiles[filePath], | |
ts.ScriptTarget.Latest | |
); | |
return compiledFiles[filePath]; | |
}, | |
readFile: (filePath) => { | |
// console.log("read", filePath); | |
return rawFiles[filePath]; | |
}, | |
useCaseSensitiveFileNames: () => true, | |
writeFile: (fileName, data) => { | |
console.log("ts write >", fileName, data); | |
}, | |
}; | |
const program = ts.createProgram({ | |
options, | |
rootNames: root, | |
host, | |
}); | |
return ts.getPreEmitDiagnostics(program); | |
} | |
import fs from "fs/promises"; | |
import path from "path"; | |
import zlib from "zlib"; | |
const tsSourcePath = path.join(__dirname, "../node_modules/typescript/lib/"); | |
async function readLibFiles(): Promise<Files> { | |
const libFiles = await fs.readdir(tsSourcePath); | |
const entries = await Promise.all( | |
libFiles | |
.filter((file) => file.startsWith("lib.") && file.endsWith(".d.ts")) | |
.map(async (f) => { | |
const content = await fs.readFile(path.join(tsSourcePath, f), "utf8"); | |
return [`/_libs/${f}`, content]; | |
}) | |
); | |
return Object.fromEntries(entries); | |
} | |
const dumpPath = path.join(__dirname, "libs.json.gz"); | |
async function dumpLibsFile(libFiles: Files) { | |
const zipped = zlib.gzipSync(JSON.stringify(libFiles)); | |
await fs.writeFile(dumpPath, zipped); | |
console.log("gen >", "libs.json.gz", zipped.length); | |
} | |
async function loadLibsFile(): Promise<Files> { | |
const buf = await fs.readFile(dumpPath); | |
const text = zlib.gunzipSync(buf).toString("utf-8"); | |
return JSON.parse(text); | |
} | |
async function main() { | |
const libFiles = await readLibFiles(); | |
// await dumpLibsFile(libFiles); | |
// from saved | |
// const libFiles = await loadLibsFile(); | |
const rawFiles: Files = { | |
"/file.ts": "export const x: number = false", | |
"/input.ts": `import { x } from "./file"; 1 as false;`, | |
}; | |
const ret = getDiagnostics({ ...libFiles, ...rawFiles }, ["/input.ts"]); | |
for (const d of ret) { | |
// @ts-ignore | |
console.log(d.file?.fileName, d.messageText); | |
} | |
} | |
main().catch((e) => console.error(e)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Use case: check deno permission subset
Result