UNPKG

@neo-one/smart-contract-compiler

Version:

NEO•ONE TypeScript smart contract compiler.

89 lines (87 loc) 15.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const ts_utils_1 = require("@neo-one/ts-utils"); const utils_1 = require("@neo-one/utils"); const typescript_1 = tslib_1.__importDefault(require("typescript")); const createContext_1 = require("./createContext"); const errors_1 = require("./errors"); exports.scanContext = (context) => { const smartContract = ts_utils_1.tsUtils.symbol.getDeclarations(context.builtins.getValueSymbol('SmartContract'))[0]; if (!typescript_1.default.isClassDeclaration(smartContract)) { throw new Error('Something went wrong!'); } const { contracts, dependencies } = ts_utils_1.tsUtils.class_ .getExtendors(context.program, context.languageService, smartContract) .reduce((acc, derived) => { if (!ts_utils_1.tsUtils.modifier.isAbstract(derived) && !ts_utils_1.tsUtils.file.isDeclarationFile(ts_utils_1.tsUtils.node.getSourceFile(derived))) { const filePath = ts_utils_1.tsUtils.file.getFilePath(ts_utils_1.tsUtils.node.getSourceFile(derived)); const name = ts_utils_1.tsUtils.node.getNameOrThrow(derived); const existing = acc.contracts[filePath]; if (existing !== undefined) { throw new errors_1.MultipleContractsInFileError(filePath); } const references = [ ...new Set(ts_utils_1.tsUtils.reference .findReferencesAsNodes(context.program, context.languageService, derived) .map((reference) => ts_utils_1.tsUtils.file.getFilePath(ts_utils_1.tsUtils.node.getSourceFile(reference)))), ]; const dependency = { filePath, name }; const dependenciesOut = references.reduce((innerAcc, reference) => { let filePathDependencies = innerAcc[reference]; if (filePathDependencies === undefined) { filePathDependencies = []; } return Object.assign({}, innerAcc, { [reference]: [...filePathDependencies, dependency] }); }, acc.dependencies); return { contracts: Object.assign({}, acc.contracts, { [filePath]: { filePath, name, dependencies: [], } }), dependencies: dependenciesOut, }; } return acc; }, { contracts: {}, dependencies: {} }); const unsortedContracts = Object.values(contracts).map((contract) => { const filePathDependencies = dependencies[contract.filePath]; return Object.assign({}, contract, { dependencies: filePathDependencies === undefined ? [] : filePathDependencies }); }); return topographicalSort(unsortedContracts); }; const topographicalSort = (contracts) => { const contractToDependencies = contracts.reduce((acc, contract) => (Object.assign({}, acc, { [contract.filePath]: new Set(contract.dependencies.map((dep) => dep.filePath)) })), {}); const mutableOut = []; const satisfied = contracts.filter((contract) => contract.dependencies.length === 0); let remaining = contracts.filter((contract) => contract.dependencies.length !== 0); while (satisfied.length > 0) { const node = satisfied.shift(); if (node === undefined) { break; } mutableOut.push(node); remaining = remaining .map((contract) => { const deps = contractToDependencies[contract.filePath]; deps.delete(node.filePath); if (deps.size === 0) { satisfied.push(contract); return undefined; } return contract; }) .filter(utils_1.utils.notNull); } if (mutableOut.length !== contracts.length) { throw new errors_1.CircularLinkedDependencyError(contracts.map((contract) => contract.name)); } return mutableOut; }; exports.scan = async (dir, host) => { const context = await createContext_1.createContextForDir(dir, host); return exports.scanContext(context); }; //# sourceMappingURL=data:application/json;charset=utf8;base64,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LENBQUM7SUFFckQsT0FBTyxtQkFBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQzlCLENBQUMsQ0FBQyIsImZpbGUiOiJuZW8tb25lLXNtYXJ0LWNvbnRyYWN0LWNvbXBpbGVyL3NyYy9zY2FuLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgdHNVdGlscyB9IGZyb20gJ0BuZW8tb25lL3RzLXV0aWxzJztcbmltcG9ydCB7IHV0aWxzIH0gZnJvbSAnQG5lby1vbmUvdXRpbHMnO1xuaW1wb3J0IHRzIGZyb20gJ3R5cGVzY3JpcHQnO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gJy4vQ29udGV4dCc7XG5pbXBvcnQgeyBjcmVhdGVDb250ZXh0Rm9yRGlyIH0gZnJvbSAnLi9jcmVhdGVDb250ZXh0JztcbmltcG9ydCB7IENpcmN1bGFyTGlua2VkRGVwZW5kZW5jeUVycm9yLCBNdWx0aXBsZUNvbnRyYWN0c0luRmlsZUVycm9yIH0gZnJvbSAnLi9lcnJvcnMnO1xuaW1wb3J0IHsgQ29tcGlsZXJIb3N0IH0gZnJvbSAnLi90eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udHJhY3REZXBlbmRlbmN5IHtcbiAgcmVhZG9ubHkgZmlsZVBhdGg6IHN0cmluZztcbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xufVxuZXhwb3J0IGludGVyZmFjZSBDb250cmFjdCB7XG4gIHJlYWRvbmx5IGZpbGVQYXRoOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgZGVwZW5kZW5jaWVzOiBSZWFkb25seUFycmF5PENvbnRyYWN0RGVwZW5kZW5jeT47XG59XG5leHBvcnQgdHlwZSBDb250cmFjdHMgPSBSZWFkb25seUFycmF5PENvbnRyYWN0PjtcblxuaW50ZXJmYWNlIEZpbGVQYXRoVG9Db250cmFjdCB7XG4gIHJlYWRvbmx5IFtmaWxlUGF0aDogc3RyaW5nXTogQ29udHJhY3Q7XG59XG5pbnRlcmZhY2UgRmlsZVBhdGhUb0RlcGVuZGVuY2llcyB7XG4gIHJlYWRvbmx5IFtmaWxlUGF0aDogc3RyaW5nXTogUmVhZG9ubHlBcnJheTxDb250cmFjdERlcGVuZGVuY3k+O1xufVxuXG5leHBvcnQgY29uc3Qgc2NhbkNvbnRleHQgPSAoY29udGV4dDogQ29udGV4dCk6IENvbnRyYWN0cyA9PiB7XG4gIGNvbnN0IHNtYXJ0Q29udHJhY3QgPSB0c1V0aWxzLnN5bWJvbC5nZXREZWNsYXJhdGlvbnMoY29udGV4dC5idWlsdGlucy5nZXRWYWx1ZVN5bWJvbCgnU21hcnRDb250cmFjdCcpKVswXTtcbiAgaWYgKCF0cy5pc0NsYXNzRGVjbGFyYXRpb24oc21hcnRDb250cmFjdCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1NvbWV0aGluZyB3ZW50IHdyb25nIScpO1xuICB9XG5cbiAgY29uc3QgeyBjb250cmFjdHMsIGRlcGVuZGVuY2llcyB9ID0gdHNVdGlscy5jbGFzc19cbiAgICAuZ2V0RXh0ZW5kb3JzKGNvbnRleHQucHJvZ3JhbSwgY29udGV4dC5sYW5ndWFnZVNlcnZpY2UsIHNtYXJ0Q29udHJhY3QpXG4gICAgLnJlZHVjZTx7IGNvbnRyYWN0czogRmlsZVBhdGhUb0NvbnRyYWN0OyBkZXBlbmRlbmNpZXM6IEZpbGVQYXRoVG9EZXBlbmRlbmNpZXMgfT4oXG4gICAgICAoYWNjLCBkZXJpdmVkKSA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAhdHNVdGlscy5tb2RpZmllci5pc0Fic3RyYWN0KGRlcml2ZWQpICYmXG4gICAgICAgICAgIXRzVXRpbHMuZmlsZS5pc0RlY2xhcmF0aW9uRmlsZSh0c1V0aWxzLm5vZGUuZ2V0U291cmNlRmlsZShkZXJpdmVkKSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc3QgZmlsZVBhdGggPSB0c1V0aWxzLmZpbGUuZ2V0RmlsZVBhdGgodHNVdGlscy5ub2RlLmdldFNvdXJjZUZpbGUoZGVyaXZlZCkpO1xuICAgICAgICAgIGNvbnN0IG5hbWUgPSB0c1V0aWxzLm5vZGUuZ2V0TmFtZU9yVGhyb3coZGVyaXZlZCk7XG4gICAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBhY2MuY29udHJhY3RzW2ZpbGVQYXRoXSBhcyBDb250cmFjdCB8IHVuZGVmaW5lZDtcbiAgICAgICAgICBpZiAoZXhpc3RpbmcgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IE11bHRpcGxlQ29udHJhY3RzSW5GaWxlRXJyb3IoZmlsZVBhdGgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHJlZmVyZW5jZXMgPSBbXG4gICAgICAgICAgICAuLi5uZXcgU2V0KFxuICAgICAgICAgICAgICB0c1V0aWxzLnJlZmVyZW5jZVxuICAgICAgICAgICAgICAgIC5maW5kUmVmZXJlbmNlc0FzTm9kZXMoY29udGV4dC5wcm9ncmFtLCBjb250ZXh0Lmxhbmd1YWdlU2VydmljZSwgZGVyaXZlZClcbiAgICAgICAgICAgICAgICAubWFwKChyZWZlcmVuY2UpID0+IHRzVXRpbHMuZmlsZS5nZXRGaWxlUGF0aCh0c1V0aWxzLm5vZGUuZ2V0U291cmNlRmlsZShyZWZlcmVuY2UpKSksXG4gICAgICAgICAgICApLFxuICAgICAgICAgIF07XG5cbiAgICAgICAgICBjb25zdCBkZXBlbmRlbmN5ID0geyBmaWxlUGF0aCwgbmFtZSB9O1xuICAgICAgICAgIGNvbnN0IGRlcGVuZGVuY2llc091dCA9IHJlZmVyZW5jZXMucmVkdWNlKChpbm5lckFjYywgcmVmZXJlbmNlKSA9PiB7XG4gICAgICAgICAgICBsZXQgZmlsZVBhdGhEZXBlbmRlbmNpZXMgPSBpbm5lckFjY1tyZWZlcmVuY2VdIGFzIFJlYWRvbmx5QXJyYXk8Q29udHJhY3REZXBlbmRlbmN5PiB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmIChmaWxlUGF0aERlcGVuZGVuY2llcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIGZpbGVQYXRoRGVwZW5kZW5jaWVzID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIC4uLmlubmVyQWNjLFxuICAgICAgICAgICAgICBbcmVmZXJlbmNlXTogWy4uLmZpbGVQYXRoRGVwZW5kZW5jaWVzLCBkZXBlbmRlbmN5XSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSwgYWNjLmRlcGVuZGVuY2llcyk7XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29udHJhY3RzOiB7XG4gICAgICAgICAgICAgIC4uLmFjYy5jb250cmFjdHMsXG4gICAgICAgICAgICAgIFtmaWxlUGF0aF06IHtcbiAgICAgICAgICAgICAgICBmaWxlUGF0aCxcbiAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgICAgIGRlcGVuZGVuY2llczogW10sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVwZW5kZW5jaWVzOiBkZXBlbmRlbmNpZXNPdXQsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhY2M7XG4gICAgICB9LFxuICAgICAgeyBjb250cmFjdHM6IHt9LCBkZXBlbmRlbmNpZXM6IHt9IH0sXG4gICAgKTtcblxuICBjb25zdCB1bnNvcnRlZENvbnRyYWN0cyA9IE9iamVjdC52YWx1ZXMoY29udHJhY3RzKS5tYXAoKGNvbnRyYWN0KSA9PiB7XG4gICAgY29uc3QgZmlsZVBhdGhEZXBlbmRlbmNpZXMgPSBkZXBlbmRlbmNpZXNbY29udHJhY3QuZmlsZVBhdGhdIGFzIFJlYWRvbmx5QXJyYXk8Q29udHJhY3REZXBlbmRlbmN5PiB8IHVuZGVmaW5lZDtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi5jb250cmFjdCxcbiAgICAgIGRlcGVuZGVuY2llczogZmlsZVBhdGhEZXBlbmRlbmNpZXMgPT09IHVuZGVmaW5lZCA/IFtdIDogZmlsZVBhdGhEZXBlbmRlbmNpZXMsXG4gICAgfTtcbiAgfSk7XG5cbiAgcmV0dXJuIHRvcG9ncmFwaGljYWxTb3J0KHVuc29ydGVkQ29udHJhY3RzKTtcbn07XG5cbmNvbnN0IHRvcG9ncmFwaGljYWxTb3J0ID0gKGNvbnRyYWN0czogQ29udHJhY3RzKTogQ29udHJhY3RzID0+IHtcbiAgY29uc3QgY29udHJhY3RUb0RlcGVuZGVuY2llcyA9IGNvbnRyYWN0cy5yZWR1Y2U8eyBbZmlsZVBhdGg6IHN0cmluZ106IFNldDxzdHJpbmc+IH0+KFxuICAgIChhY2MsIGNvbnRyYWN0KSA9PiAoe1xuICAgICAgLi4uYWNjLFxuICAgICAgW2NvbnRyYWN0LmZpbGVQYXRoXTogbmV3IFNldChjb250cmFjdC5kZXBlbmRlbmNpZXMubWFwKChkZXApID0+IGRlcC5maWxlUGF0aCkpLFxuICAgIH0pLFxuICAgIHt9LFxuICApO1xuICBjb25zdCBtdXRhYmxlT3V0OiBDb250cmFjdFtdID0gW107XG4gIGNvbnN0IHNhdGlzZmllZCA9IGNvbnRyYWN0cy5maWx0ZXIoKGNvbnRyYWN0KSA9PiBjb250cmFjdC5kZXBlbmRlbmNpZXMubGVuZ3RoID09PSAwKTtcbiAgbGV0IHJlbWFpbmluZyA9IGNvbnRyYWN0cy5maWx0ZXIoKGNvbnRyYWN0KSA9PiBjb250cmFjdC5kZXBlbmRlbmNpZXMubGVuZ3RoICE9PSAwKTtcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWxvb3Atc3RhdGVtZW50XG4gIHdoaWxlIChzYXRpc2ZpZWQubGVuZ3RoID4gMCkge1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1hcnJheS1tdXRhdGlvblxuICAgIGNvbnN0IG5vZGUgPSBzYXRpc2ZpZWQuc2hpZnQoKTtcbiAgICBpZiAobm9kZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgbXV0YWJsZU91dC5wdXNoKG5vZGUpO1xuICAgIHJlbWFpbmluZyA9IHJlbWFpbmluZ1xuICAgICAgLm1hcCgoY29udHJhY3QpID0+IHtcbiAgICAgICAgY29uc3QgZGVwcyA9IGNvbnRyYWN0VG9EZXBlbmRlbmNpZXNbY29udHJhY3QuZmlsZVBhdGhdO1xuICAgICAgICBkZXBzLmRlbGV0ZShub2RlLmZpbGVQYXRoKTtcbiAgICAgICAgaWYgKGRlcHMuc2l6ZSA9PT0gMCkge1xuICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1hcnJheS1tdXRhdGlvblxuICAgICAgICAgIHNhdGlzZmllZC5wdXNoKGNvbnRyYWN0KTtcblxuICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29udHJhY3Q7XG4gICAgICB9KVxuICAgICAgLmZpbHRlcih1dGlscy5ub3ROdWxsKTtcbiAgfVxuXG4gIGlmIChtdXRhYmxlT3V0Lmxlbmd0aCAhPT0gY29udHJhY3RzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBDaXJjdWxhckxpbmtlZERlcGVuZGVuY3lFcnJvcihjb250cmFjdHMubWFwKChjb250cmFjdCkgPT4gY29udHJhY3QubmFtZSkpO1xuICB9XG5cbiAgcmV0dXJuIG11dGFibGVPdXQ7XG59O1xuXG5leHBvcnQgY29uc3Qgc2NhbiA9IGFzeW5jIChkaXI6IHN0cmluZywgaG9zdDogQ29tcGlsZXJIb3N0KTogUHJvbWlzZTxDb250cmFjdHM+ID0+IHtcbiAgY29uc3QgY29udGV4dCA9IGF3YWl0IGNyZWF0ZUNvbnRleHRGb3JEaXIoZGlyLCBob3N0KTtcblxuICByZXR1cm4gc2NhbkNvbnRleHQoY29udGV4dCk7XG59O1xuIl19