UNPKG

tstosc

Version:

A transpiler that convert TypeScript to SuperCollider's SCLang.

118 lines (115 loc) 4.08 kB
import ts from 'typescript'; import { Result } from '../../util/Result.js'; class Analyser { static default_compiler_option = { noEmit: true, lib: ["lib.esnext.full.d.ts"], target: ts.ScriptTarget.ESNext, module: ts.ModuleKind.ESNext, esModuleInterop: true, moduleResolution: ts.ModuleResolutionKind.Bundler }; static default_compiler_host = ts.createCompilerHost( Analyser.default_compiler_option, true // Not forget to let it set parent node. ); static virtual_file_name = "virtual_file__do_not_really_exist.ts"; static default_constructor_args = { root_files_path: [] }; program; constructor(args = Analyser.default_constructor_args) { const root_files_path = "root_files_path" in args ? args.root_files_path : args.files.map((f) => f.input_path); this.program = ts.createProgram({ rootNames: root_files_path, options: Analyser.default_compiler_option, host: Analyser.default_compiler_host }); } /** * The most important feature of `Analyser`. * * This function returns the configured `ts.Program` which handles all inputed files. */ getCompilerProgram() { return this.program; } /** * Get the Abstract Syntax Tree (AST, with type `ts.SourceFile`) of a TypeScript file. * * @param path If relative, the `.` stands for the working directory when `tstosc` starts. * Be careful that the file you want to get AST from, must be **in** the `root_files_path`, * or **being referenced** by the files in the `root_files_path`. */ getASTOfFile(file_path) { return this.program.getSourceFile(file_path); } static buildASTFromCode(source_code) { const ts_source_file = ts.createSourceFile( Analyser.virtual_file_name, source_code, ts.ScriptTarget.Latest, true // From ChatGPT: Set to `true` to enable syntax tree preservation ); { const possible_errors = Analyser.preCheckErrorsBeforeBuildAST({ ts_source_file }); if (possible_errors.length > 0) { return Result.createErr({ error_type: "input_is_not_valid_ts" /* input_is_not_valid_ts */, details: possible_errors }); } } return Result.createOk(ts_source_file); } static preCheckErrorsBeforeBuildAST({ ts_source_file }) { const host = { ...Analyser.default_compiler_host, getSourceFile: (file_name, language_version) => { if (file_name == ts_source_file.fileName) { return ts_source_file; } else { return Analyser.default_compiler_host.getSourceFile(file_name, language_version); } }, getDefaultLibFileName: () => ts.getDefaultLibFileName(Analyser.default_compiler_option) }; return ts.getPreEmitDiagnostics( ts.createProgram({ rootNames: [ts_source_file.fileName], options: Analyser.default_compiler_option, host }) ).map( function(d) { const error_message = ts.flattenDiagnosticMessageText(d.messageText, "\n"); if (d.file != void 0 && d.start != void 0) { const { line, character } = ts.getLineAndCharacterOfPosition(d.file, d.start); return { is_compiler_error: false, position_line: line + 1, position_column: character + 1, message: error_message }; } else { return { is_compiler_error: true, message: error_message }; } } ); } checkIfExistsUnsupportSyntax() { } traverseTSNode(ts_node, action) { action(ts_node); ts.forEachChild(ts_node, action); } } var BuildASTFailErrorType = /* @__PURE__ */ ((BuildASTFailErrorType2) => { BuildASTFailErrorType2["input_is_not_valid_ts"] = "input_is_not_valid_ts"; BuildASTFailErrorType2["input_contains_unsupported_syntax"] = "input_contains_unsupported_syntax"; return BuildASTFailErrorType2; })(BuildASTFailErrorType || {}); function getASTFromCode(source_code) { return Analyser.buildASTFromCode(source_code); } export { Analyser, BuildASTFailErrorType, getASTFromCode };