@neo-one/smart-contract-compiler
Version:
NEO•ONE TypeScript smart contract compiler.
115 lines (113 loc) • 5.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createContextForLanguageService = exports.createContextForSnippet = exports.createContextForPath = exports.createContextForDir = exports.COMPILER_OPTIONS = exports.updateContext = void 0;
const tslib_1 = require("tslib");
const ts_utils_1 = require("@neo-one/ts-utils");
const typescript_1 = tslib_1.__importDefault(require("typescript"));
const Context_1 = require("./Context");
const utils_1 = require("./utils");
function createContext(sourceFiles, program, typeChecker, languageService, host) {
return new Context_1.Context(sourceFiles, program, typeChecker, languageService, host);
}
function updateContext(context, files) {
const { program, typeChecker, languageService } = createProgram(Object.keys(files), context.host, {
modifyHost: createModifyHostFiles(files),
withTestHarness: context.program.__withTestHarness,
});
const sourceFiles = utils_1.getAllSourceFiles(Object.keys(files).map((rootName) => ts_utils_1.tsUtils.file.getSourceFileOrThrow(program, rootName)), typeChecker);
return context.update(sourceFiles, program, typeChecker, languageService);
}
exports.updateContext = updateContext;
const CREATE_CONTEXT_OPTIONS_DEFAULT = {
withTestHarness: false,
};
const defaultModifyHost = () => {
};
const DEFAULT_MAKE_CONTEXT_OPTIONS = Object.assign(Object.assign({}, CREATE_CONTEXT_OPTIONS_DEFAULT), { modifyHost: defaultModifyHost });
exports.COMPILER_OPTIONS = {
target: typescript_1.default.ScriptTarget.ESNext,
module: typescript_1.default.ModuleKind.ESNext,
moduleResolution: typescript_1.default.ModuleResolutionKind.NodeJs,
noLib: true,
typeRoots: [],
pretty: true,
noEmit: true,
declaration: false,
allowSyntheticDefaultImports: true,
resolveJsonModule: false,
experimentalDecorators: true,
jsx: typescript_1.default.JsxEmit.React,
alwaysStrict: true,
strict: true,
skipLibCheck: true,
noUnusedLocals: true,
noImplicitReturns: true,
allowUnusedLabels: false,
noUnusedParameters: false,
allowUnreachableCode: false,
noFallthroughCasesInSwitch: true,
forceConsistentCasingInFileNames: true,
};
const makeContext = (rootNames, host, options = DEFAULT_MAKE_CONTEXT_OPTIONS) => {
const { program, typeChecker, languageService } = createProgram(rootNames, host, options);
const sourceFiles = utils_1.getAllSourceFiles(rootNames.map((rootName) => ts_utils_1.tsUtils.file.getSourceFileOrThrow(program, rootName)), typeChecker);
return createContext(sourceFiles, program, typeChecker, languageService, host);
};
const createModifyHostFiles = (files) => (host) => {
const originalFileExists = host.fileExists === undefined ? undefined : host.fileExists.bind(host);
host.fileExists = (file) => {
if (files[file] !== undefined) {
return true;
}
return originalFileExists === undefined ? false : originalFileExists(file);
};
const originalReadFile = host.readFile === undefined ? undefined : host.readFile.bind(host);
host.readFile = (file, ...args) => {
const foundFile = files[file];
if (foundFile !== undefined) {
return foundFile;
}
return originalReadFile === undefined ? undefined : originalReadFile(file, ...args);
};
};
const createProgram = (rootNames, host, { modifyHost = defaultModifyHost, withTestHarness = false } = DEFAULT_MAKE_CONTEXT_OPTIONS) => {
const servicesHost = host.createLanguageServiceHost(rootNames, exports.COMPILER_OPTIONS, withTestHarness);
modifyHost(servicesHost);
const languageService = typescript_1.default.createLanguageService(servicesHost);
const program = languageService.getProgram();
if (program === undefined) {
throw new Error('Something went wrong');
}
program.__withTestHarness = withTestHarness;
return {
program,
typeChecker: program.getTypeChecker(),
languageService,
};
};
exports.createContextForDir = async (dir, host, options = CREATE_CONTEXT_OPTIONS_DEFAULT) => {
const files = await host.getAllTypescriptFilesInDir(dir);
return makeContext(files, host, options);
};
exports.createContextForPath = (filePath, host, options = CREATE_CONTEXT_OPTIONS_DEFAULT) => makeContext([filePath], host, options);
exports.createContextForSnippet = (code, host, _a = CREATE_CONTEXT_OPTIONS_DEFAULT) => {
var { fileName: fileNameIn } = _a, rest = tslib_1.__rest(_a, ["fileName"]);
const fileName = host.createSnippetFile(fileNameIn);
const context = makeContext([fileName], host, Object.assign(Object.assign({}, rest), { modifyHost: createModifyHostFiles({ [fileName]: code }) }));
const sourceFile = ts_utils_1.tsUtils.file.getSourceFileOrThrow(context.program, fileName);
return {
context,
sourceFile,
};
};
exports.createContextForLanguageService = (filePath, languageService, host) => {
const program = languageService.getProgram();
if (program === undefined) {
throw new Error('Something went wrong');
}
const sourceFile = ts_utils_1.tsUtils.file.getSourceFileOrThrow(program, filePath);
const typeChecker = program.getTypeChecker();
const sourceFiles = utils_1.getAllSourceFiles([sourceFile], typeChecker);
return createContext(sourceFiles, program, typeChecker, languageService, host);
};
//# sourceMappingURL=createContext.js.map