roblox-ts
Version:
A TypeScript-to-Luau Compiler for Roblox
120 lines • 6.77 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.VirtualProject = void 0;
const luau_ast_1 = require("@roblox-ts/luau-ast");
const path_translator_1 = require("@roblox-ts/path-translator");
const rojo_resolver_1 = require("@roblox-ts/rojo-resolver");
const VirtualFileSystem_1 = require("./VirtualFileSystem");
const validateCompilerOptions_1 = require("../functions/validateCompilerOptions");
const getCustomPreEmitDiagnostics_1 = require("../util/getCustomPreEmitDiagnostics");
const constants_1 = require("../../Shared/constants");
const DiagnosticError_1 = require("../../Shared/errors/DiagnosticError");
const assert_1 = require("../../Shared/util/assert");
const hasErrors_1 = require("../../Shared/util/hasErrors");
const TSTransformer_1 = require("../../TSTransformer");
const DiagnosticService_1 = require("../../TSTransformer/classes/DiagnosticService");
const createTransformServices_1 = require("../../TSTransformer/util/createTransformServices");
const typescript_1 = __importDefault(require("typescript"));
const PROJECT_DIR = VirtualFileSystem_1.PATH_SEP;
const ROOT_DIR = (0, VirtualFileSystem_1.pathJoin)(PROJECT_DIR, "src");
const OUT_DIR = (0, VirtualFileSystem_1.pathJoin)(PROJECT_DIR, "out");
const PLAYGROUND_PATH = (0, VirtualFileSystem_1.pathJoin)(ROOT_DIR, "playground.tsx");
const NODE_MODULES_PATH = (0, VirtualFileSystem_1.pathJoin)(PROJECT_DIR, constants_1.NODE_MODULES);
const RBXTS_SCOPE_PATH = (0, VirtualFileSystem_1.pathJoin)(NODE_MODULES_PATH, constants_1.RBXTS_SCOPE);
const INCLUDE_PATH = (0, VirtualFileSystem_1.pathJoin)(PROJECT_DIR, "include");
class VirtualProject {
constructor() {
this.nodeModulesPathMapping = new Map();
this.data = {
isPackage: false,
nodeModulesPath: NODE_MODULES_PATH,
projectOptions: Object.assign({}, constants_1.DEFAULT_PROJECT_OPTIONS, {
rojo: "",
type: constants_1.ProjectType.Model,
optimizedLoops: true,
}),
projectPath: PROJECT_DIR,
rojoConfigPath: undefined,
tsConfigPath: "",
};
this.compilerOptions = {
allowSyntheticDefaultImports: true,
downlevelIteration: true,
noLib: true,
strict: true,
target: typescript_1.default.ScriptTarget.ESNext,
module: typescript_1.default.ModuleKind.CommonJS,
moduleResolution: typescript_1.default.ModuleResolutionKind.Node10,
moduleDetection: typescript_1.default.ModuleDetectionKind.Force,
typeRoots: [RBXTS_SCOPE_PATH],
resolveJsonModule: true,
experimentalDecorators: true,
rootDir: ROOT_DIR,
outDir: OUT_DIR,
jsx: typescript_1.default.JsxEmit.React,
jsxFactory: "React.createElement",
jsxFragmentFactory: "React.Fragment",
};
(0, validateCompilerOptions_1.validateCompilerOptions)(this.compilerOptions, this.data.projectPath);
this.vfs = new VirtualFileSystem_1.VirtualFileSystem();
const system = {
getExecutingFilePath: () => __filename,
getCurrentDirectory: () => "/",
};
this.compilerHost = typescript_1.default.createCompilerHostWorker(this.compilerOptions, undefined, system);
this.compilerHost.readFile = filePath => this.vfs.readFile(filePath);
this.compilerHost.fileExists = filePath => this.vfs.fileExists(filePath);
this.compilerHost.directoryExists = dirPath => this.vfs.directoryExists(dirPath);
this.compilerHost.getDirectories = dirPath => this.vfs.getDirectories(dirPath);
this.compilerHost.useCaseSensitiveFileNames = () => true;
this.compilerHost.getCurrentDirectory = () => VirtualFileSystem_1.PATH_SEP;
this.rojoResolver = rojo_resolver_1.RojoResolver.fromTree(PROJECT_DIR, {
$path: OUT_DIR,
include: {
$path: INCLUDE_PATH,
node_modules: {
$className: "Folder",
"@rbxts": {
$path: RBXTS_SCOPE_PATH,
},
},
},
});
this.pkgRojoResolvers = this.compilerOptions.typeRoots.map(rojo_resolver_1.RojoResolver.synthetic);
}
compileSource(source) {
this.vfs.writeFile(PLAYGROUND_PATH, source);
const rootNames = this.vfs
.getFilePaths()
.filter(v => v.endsWith(typescript_1.default.Extension.Ts) || v.endsWith(typescript_1.default.Extension.Tsx) || v.endsWith(typescript_1.default.Extension.Dts));
this.program = typescript_1.default.createProgram(rootNames, this.compilerOptions, this.compilerHost, this.program);
this.typeChecker = this.program.getTypeChecker();
const services = (0, createTransformServices_1.createTransformServices)(this.typeChecker);
const pathTranslator = new path_translator_1.PathTranslator(ROOT_DIR, OUT_DIR, undefined, false, this.data.projectOptions.luau);
const sourceFile = this.program.getSourceFile(PLAYGROUND_PATH);
(0, assert_1.assert)(sourceFile);
const diagnostics = new Array();
diagnostics.push(...typescript_1.default.getPreEmitDiagnostics(this.program, sourceFile));
diagnostics.push(...(0, getCustomPreEmitDiagnostics_1.getCustomPreEmitDiagnostics)(this.data, sourceFile));
if ((0, hasErrors_1.hasErrors)(diagnostics))
throw new DiagnosticError_1.DiagnosticError(diagnostics);
const multiTransformState = new TSTransformer_1.MultiTransformState();
const runtimeLibRbxPath = undefined;
const projectType = this.data.projectOptions.type;
const transformState = new TSTransformer_1.TransformState(this.program, this.data, services, pathTranslator, multiTransformState, this.compilerOptions, this.rojoResolver, this.pkgRojoResolvers, this.nodeModulesPathMapping, runtimeLibRbxPath, this.typeChecker, projectType, sourceFile);
const luaAST = (0, TSTransformer_1.transformSourceFile)(transformState, sourceFile);
diagnostics.push(...DiagnosticService_1.DiagnosticService.flush());
if ((0, hasErrors_1.hasErrors)(diagnostics))
throw new DiagnosticError_1.DiagnosticError(diagnostics);
const luaSource = (0, luau_ast_1.renderAST)(luaAST);
return luaSource;
}
setMapping(typings, main) {
this.nodeModulesPathMapping.set(typings, main);
}
}
exports.VirtualProject = VirtualProject;
//# sourceMappingURL=VirtualProject.js.map