dragonbones-runtime
Version:
the tools to build dragonbones file for diffrent framework
195 lines (172 loc) • 6.92 kB
text/typescript
import utils = require('../lib/utils');
import file = require('../lib/FileUtil');
import ts = require("../lib/typescript-plus/lib/typescript");
import * as path from 'path';
export interface EgretCompilerHost {
program: ts.Program;
files?: string[];
exitStatus: number;
compileWithChanges: (filesChanged: egret.FileChanges, sourceMap?: boolean) => EgretCompilerHost;
messages?: string[];
}
let compilerHost: ts.CompilerHost;
let hostGetSourceFile;
let hostFileExists;
let cachedProgram: ts.Program;
let cachedExistingFiles: utils.Map<boolean>;
let changedFileNames: Array<string> = [];
let getSourceFile = function (fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void) {
if (cachedProgram && changedFileNames.indexOf(fileName) == -1) {
const sourceFile = cachedProgram.getSourceFile(fileName);
if (sourceFile) {
return sourceFile;
}
}
const sourceFile = hostGetSourceFile(fileName, languageVersion, onError);
return sourceFile;
}
let cachedFileExists = function (fileName: string): boolean {
return fileName in cachedExistingFiles
? cachedExistingFiles[fileName]
: cachedExistingFiles[fileName] = hostFileExists(fileName);
}
export class Compiler {
private sortedFiles: string[];
private program: ts.Program;
private options: ts.CompilerOptions;
public compile(options: ts.CompilerOptions, rootFileNames: string[]): EgretCompilerHost {
this.fileNames = rootFileNames;
this.options = options;
cachedProgram = null;
compilerHost = ts.createCompilerHost(options);
hostGetSourceFile = compilerHost.getSourceFile;
compilerHost.getSourceFile = getSourceFile;
hostFileExists = compilerHost.fileExists;
compilerHost.fileExists = cachedFileExists;
return this.doCompile();
}
private sortFiles(): void {
let program = this.program;
let sortResult = ts.reorderSourceFiles(program);
if (sortResult.circularReferences.length > 0) {
let error: string = "";
error += "error: circular references '" + "' :" + ts.sys.newLine;
error += " at " + sortResult.circularReferences.join(ts.sys.newLine + " at ") + ts.sys.newLine + " at ...";
console.log(error);
this.errors.push(error);
}
this.sortedFiles = sortResult.sortedFileNames;
}
private errors: string[] = [];
private logErrors(diagnostics) {
let allDiagnostics = ts.getPreEmitDiagnostics(this.program).concat(diagnostics);
allDiagnostics.forEach(diagnostic => {
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
let msg;
if (diagnostic.file) {
let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
msg = ` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`;
}
else {
msg = ` Error: ${message}`;
}
console.log(msg);
if (this.errors.length < 100) {
this.errors.push(msg);
}
});
}
private fileNames: Array<string>;
compileWithChanges(filesChanged: egret.FileChanges, sourceMap?: boolean): EgretCompilerHost {
this.errors = [];
changedFileNames = [];
let hasAddOrRemoved = false;
filesChanged.forEach(file => {
if (file.type == "added") {
hasAddOrRemoved = true;
this.fileNames.push(file.fileName);
}
else if (file.type == "removed") {
hasAddOrRemoved = true;
var index = this.fileNames.indexOf(file.fileName);
if (index >= 0) {
this.fileNames.splice(index, 1);
}
}
else {
changedFileNames.push(file.fileName);
}
});
if (hasAddOrRemoved) {
cachedProgram = undefined;
}
return this.doCompile();
}
private doCompile(): EgretCompilerHost {
cachedExistingFiles = utils.createMap<boolean>();
this.program = ts.createProgram(this.fileNames, this.options, compilerHost);
this.sortFiles();
let emitResult = this.program.emit();
this.logErrors(emitResult.diagnostics);
cachedProgram = this.program;
return { files: this.sortedFiles, program: this.program, exitStatus: 0, messages: this.errors, compileWithChanges: this.compileWithChanges.bind(this) };
}
parseTsconfig(projectRoot: string, isPublish: boolean) {
let url = projectRoot + "tsconfig.json";
var configObj: any;
try {
configObj = JSON.parse(file.read(url));
} catch (e) {
console.log(utils.tr(1117))//不是有效的 json 文件
// errLog.push();
configObj = {
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"lib": [
"es5", "dom", "es2015.promise"
]
},
"exclude": [
"node_modules"
]
}
}
let notSupport = ["module", "noLib", "rootDir", "out"];
let defaultSupport = { outDir: "bin-debug" };
let compilerOptions = configObj.compilerOptions;
for (let optionName of notSupport) {
if (compilerOptions.hasOwnProperty(optionName)) {
var error = utils.tr(1116, optionName);//这个编译选项目前不支持修改
console.log(error);//build -e 的时候输出
delete compilerOptions[optionName];
}
}
for (let optionName in defaultSupport) {
if (compilerOptions[optionName] != defaultSupport[optionName]) {
if (compilerOptions[optionName]) {
var error = utils.tr(1116, optionName);
error = utils.tr(1123, error, defaultSupport[optionName]);
console.log(error);
}
compilerOptions[optionName] = defaultSupport[optionName];
}
}
var configParseResult = ts.parseJsonConfigFileContent(configObj, ts.sys, path.dirname(url));
compilerOptions = configParseResult.options;
compilerOptions.defines = getCompilerDefines(isPublish);
return configParseResult
}
}
function getCompilerDefines(isPublish: boolean) {
let defines: any = {};
if (isPublish) {
defines.DEBUG = false;
defines.RELEASE = true;
}
else {
defines.DEBUG = true;
defines.RELEASE = false;
}
return defines;
}