tstosc
Version:
A transpiler that convert TypeScript to SuperCollider's SCLang.
118 lines (115 loc) • 4.08 kB
JavaScript
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 };