UNPKG

@neo-one/smart-contract-compiler

Version:

NEO•ONE TypeScript smart contract compiler.

115 lines (113 loc) 4.86 kB
import { tsUtils } from '@neo-one/ts-utils'; import ts from 'typescript'; import { Context } from './Context'; import { getAllSourceFiles } from './utils'; function createContext(sourceFiles, program, typeChecker, languageService, host) { return new Context(sourceFiles, program, typeChecker, languageService, host); } export function updateContext(context, files) { const { program, typeChecker, languageService } = createProgram(Object.keys(files), context.host, { modifyHost: createModifyHostFiles(files), withTestHarness: context.program.__withTestHarness, }); const sourceFiles = getAllSourceFiles(Object.keys(files).map((rootName) => tsUtils.file.getSourceFileOrThrow(program, rootName)), typeChecker); return context.update(sourceFiles, program, typeChecker, languageService); } const CREATE_CONTEXT_OPTIONS_DEFAULT = { withTestHarness: false, }; const defaultModifyHost = () => { }; const DEFAULT_MAKE_CONTEXT_OPTIONS = { ...CREATE_CONTEXT_OPTIONS_DEFAULT, modifyHost: defaultModifyHost, }; export const COMPILER_OPTIONS = { target: ts.ScriptTarget.ESNext, module: ts.ModuleKind.ESNext, moduleResolution: ts.ModuleResolutionKind.NodeJs, noLib: true, typeRoots: [], pretty: true, noEmit: true, declaration: false, allowSyntheticDefaultImports: true, resolveJsonModule: false, experimentalDecorators: true, jsx: ts.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 = getAllSourceFiles(rootNames.map((rootName) => 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, COMPILER_OPTIONS, withTestHarness); modifyHost(servicesHost); const languageService = ts.createLanguageService(servicesHost); const program = languageService.getProgram(); if (program === undefined) { throw new Error('Something went wrong'); } program.__withTestHarness = withTestHarness; return { program, typeChecker: program.getTypeChecker(), languageService, }; }; export const createContextForDir = async (dir, host, options = CREATE_CONTEXT_OPTIONS_DEFAULT) => { const files = await host.getAllTypescriptFilesInDir(dir); return makeContext(files, host, options); }; export const createContextForPath = (filePath, host, options = CREATE_CONTEXT_OPTIONS_DEFAULT) => makeContext([filePath], host, options); export const createContextForSnippet = (code, host, { fileName: fileNameIn, ...rest } = CREATE_CONTEXT_OPTIONS_DEFAULT) => { const fileName = host.createSnippetFile(fileNameIn); const context = makeContext([fileName], host, { ...rest, modifyHost: createModifyHostFiles({ [fileName]: code }), }); const sourceFile = tsUtils.file.getSourceFileOrThrow(context.program, fileName); return { context, sourceFile, }; }; export const createContextForLanguageService = (filePath, languageService, host) => { const program = languageService.getProgram(); if (program === undefined) { throw new Error('Something went wrong'); } const sourceFile = tsUtils.file.getSourceFileOrThrow(program, filePath); const typeChecker = program.getTypeChecker(); const sourceFiles = getAllSourceFiles([sourceFile], typeChecker); return createContext(sourceFiles, program, typeChecker, languageService, host); }; //# sourceMappingURL=createContext.js.map