roblox-ts
Version:
A TypeScript-to-Luau Compiler for Roblox
160 lines • 9.85 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.compileFiles = compileFiles;
const luau_ast_1 = require("@roblox-ts/luau-ast");
const rojo_resolver_1 = require("@roblox-ts/rojo-resolver");
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const checkFileName_1 = require("./checkFileName");
const checkRojoConfig_1 = require("./checkRojoConfig");
const createNodeModulesPathMapping_1 = require("./createNodeModulesPathMapping");
const transformPaths_1 = __importDefault(require("../transformers/builtin/transformPaths"));
const transformTypeReferenceDirectives_1 = require("../transformers/builtin/transformTypeReferenceDirectives");
const createTransformerList_1 = require("../transformers/createTransformerList");
const createTransformerWatcher_1 = require("../transformers/createTransformerWatcher");
const getPluginConfigs_1 = require("../transformers/getPluginConfigs");
const getCustomPreEmitDiagnostics_1 = require("../util/getCustomPreEmitDiagnostics");
const LogService_1 = require("../../Shared/classes/LogService");
const constants_1 = require("../../Shared/constants");
const assert_1 = require("../../Shared/util/assert");
const benchmark_1 = require("../../Shared/util/benchmark");
const createTextDiagnostic_1 = require("../../Shared/util/createTextDiagnostic");
const getRootDirs_1 = require("../../Shared/util/getRootDirs");
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"));
function inferProjectType(data, rojoResolver) {
if (data.isPackage) {
return constants_1.ProjectType.Package;
}
else if (rojoResolver.isGame) {
return constants_1.ProjectType.Game;
}
else {
return constants_1.ProjectType.Model;
}
}
function emitResultFailure(messageText) {
return {
emitSkipped: true,
diagnostics: [(0, createTextDiagnostic_1.createTextDiagnostic)(messageText)],
};
}
function compileFiles(program, data, pathTranslator, sourceFiles) {
var _a;
const compilerOptions = program.getCompilerOptions();
const multiTransformState = new TSTransformer_1.MultiTransformState();
const outDir = compilerOptions.outDir;
const rojoResolver = data.rojoConfigPath
? rojo_resolver_1.RojoResolver.fromPath(data.rojoConfigPath)
: rojo_resolver_1.RojoResolver.synthetic(outDir);
for (const warning of rojoResolver.getWarnings()) {
LogService_1.LogService.warn(warning);
}
(0, checkRojoConfig_1.checkRojoConfig)(data, rojoResolver, (0, getRootDirs_1.getRootDirs)(compilerOptions), pathTranslator);
for (const sourceFile of program.getSourceFiles()) {
if (!path_1.default.normalize(sourceFile.fileName).startsWith(data.nodeModulesPath)) {
(0, checkFileName_1.checkFileName)(sourceFile.fileName);
}
}
const pkgRojoResolvers = compilerOptions.typeRoots.map(rojo_resolver_1.RojoResolver.synthetic);
const nodeModulesPathMapping = (0, createNodeModulesPathMapping_1.createNodeModulesPathMapping)(compilerOptions.typeRoots);
const projectType = (_a = data.projectOptions.type) !== null && _a !== void 0 ? _a : inferProjectType(data, rojoResolver);
if (projectType !== constants_1.ProjectType.Package && data.rojoConfigPath === undefined) {
return emitResultFailure("Non-package projects must have a Rojo project file!");
}
let runtimeLibRbxPath;
if (projectType !== constants_1.ProjectType.Package) {
runtimeLibRbxPath = rojoResolver.getRbxPathFromFilePath(path_1.default.join(data.projectOptions.includePath, "RuntimeLib.lua"));
if (!runtimeLibRbxPath) {
return emitResultFailure("Rojo project contained no data for include folder!");
}
else if (rojoResolver.getNetworkType(runtimeLibRbxPath) !== rojo_resolver_1.NetworkType.Unknown) {
return emitResultFailure("Runtime library cannot be in a server-only or client-only container!");
}
else if (rojoResolver.isIsolated(runtimeLibRbxPath)) {
return emitResultFailure("Runtime library cannot be in an isolated container!");
}
}
if (DiagnosticService_1.DiagnosticService.hasErrors())
return { emitSkipped: true, diagnostics: DiagnosticService_1.DiagnosticService.flush() };
LogService_1.LogService.writeLineIfVerbose(`compiling as ${projectType}..`);
const fileWriteQueue = new Array();
const progressMaxLength = `${sourceFiles.length}/${sourceFiles.length}`.length;
let proxyProgram = program;
if (compilerOptions.plugins && compilerOptions.plugins.length > 0) {
(0, benchmark_1.benchmarkIfVerbose)(`running transformers..`, () => {
var _a;
const pluginConfigs = (0, getPluginConfigs_1.getPluginConfigs)(data.tsConfigPath);
const transformerList = (0, createTransformerList_1.createTransformerList)(program, pluginConfigs, data.projectPath);
const transformers = (0, createTransformerList_1.flattenIntoTransformers)(transformerList);
if (transformers.length > 0) {
const { service, updateFile } = ((_a = data.transformerWatcher) !== null && _a !== void 0 ? _a : (data.transformerWatcher = (0, createTransformerWatcher_1.createTransformerWatcher)(program)));
const transformResult = typescript_1.default.transformNodes(undefined, undefined, typescript_1.default.factory, compilerOptions, sourceFiles, transformers, false);
if (transformResult.diagnostics)
DiagnosticService_1.DiagnosticService.addDiagnostics(transformResult.diagnostics);
for (const sourceFile of transformResult.transformed) {
if (typescript_1.default.isSourceFile(sourceFile)) {
const source = typescript_1.default.createPrinter().printFile(sourceFile);
updateFile(sourceFile.fileName, source);
if (data.projectOptions.writeTransformedFiles) {
const outPath = pathTranslator.getOutputTransformedPath(sourceFile.fileName);
fs_extra_1.default.outputFileSync(outPath, source);
}
}
}
proxyProgram = service.getProgram();
}
});
}
if (DiagnosticService_1.DiagnosticService.hasErrors())
return { emitSkipped: true, diagnostics: DiagnosticService_1.DiagnosticService.flush() };
const typeChecker = proxyProgram.getTypeChecker();
const services = (0, createTransformServices_1.createTransformServices)(typeChecker);
for (let i = 0; i < sourceFiles.length; i++) {
const sourceFile = proxyProgram.getSourceFile(sourceFiles[i].fileName);
(0, assert_1.assert)(sourceFile);
const progress = `${i + 1}/${sourceFiles.length}`.padStart(progressMaxLength);
(0, benchmark_1.benchmarkIfVerbose)(`${progress} compile ${path_1.default.relative(process.cwd(), sourceFile.fileName)}`, () => {
DiagnosticService_1.DiagnosticService.addDiagnostics(typescript_1.default.getPreEmitDiagnostics(proxyProgram, sourceFile));
DiagnosticService_1.DiagnosticService.addDiagnostics((0, getCustomPreEmitDiagnostics_1.getCustomPreEmitDiagnostics)(data, sourceFile));
if (DiagnosticService_1.DiagnosticService.hasErrors())
return;
const transformState = new TSTransformer_1.TransformState(proxyProgram, data, services, pathTranslator, multiTransformState, compilerOptions, rojoResolver, pkgRojoResolvers, nodeModulesPathMapping, runtimeLibRbxPath, typeChecker, projectType, sourceFile);
const luauAST = (0, TSTransformer_1.transformSourceFile)(transformState, sourceFile);
if (DiagnosticService_1.DiagnosticService.hasErrors())
return;
const source = (0, luau_ast_1.renderAST)(luauAST);
fileWriteQueue.push({ sourceFile, source });
});
}
if (DiagnosticService_1.DiagnosticService.hasErrors())
return { emitSkipped: true, diagnostics: DiagnosticService_1.DiagnosticService.flush() };
const emittedFiles = new Array();
if (fileWriteQueue.length > 0) {
(0, benchmark_1.benchmarkIfVerbose)("writing compiled files", () => {
const afterDeclarations = compilerOptions.declaration
? [transformTypeReferenceDirectives_1.transformTypeReferenceDirectives, (0, transformPaths_1.default)(program, {})]
: undefined;
for (const { sourceFile, source } of fileWriteQueue) {
const outPath = pathTranslator.getOutputPath(sourceFile.fileName);
if (!data.projectOptions.writeOnlyChanged ||
!fs_extra_1.default.pathExistsSync(outPath) ||
fs_extra_1.default.readFileSync(outPath).toString() !== source) {
fs_extra_1.default.outputFileSync(outPath, source);
emittedFiles.push(outPath);
}
if (compilerOptions.declaration) {
proxyProgram.emit(sourceFile, typescript_1.default.sys.writeFile, undefined, true, { afterDeclarations });
}
}
});
}
program.emitBuildInfo();
return { emittedFiles, emitSkipped: false, diagnostics: DiagnosticService_1.DiagnosticService.flush() };
}
//# sourceMappingURL=compileFiles.js.map