'use strict'; var module$1 = require('module'); var path = require('path'); var fs = require('fs'); var baseBundler = require('@tevm/base-bundler'); var solc = require('solc'); var utils_js = require('solidity-ast/utils.js'); var minimatch = require('minimatch'); var promises = require('fs/promises'); var bundlerCache = require('@tevm/bundler-cache'); var config = require('@tevm/config'); var Effect = require('effect/Effect'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var path__default = /*#__PURE__*/_interopDefault(path); var solc__namespace = /*#__PURE__*/_interopNamespace(solc); var __getOwnPropNames = Object.getOwnPropertyNames; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; // src/utils/isSolidity.ts var isSolidity; var init_isSolidity = __esm({ "src/utils/isSolidity.ts"() { isSolidity = (fileName) => fileName.endsWith(".sol") && !fileName.endsWith("/.sol") && fileName !== ".sol"; } }); // src/utils/isRelativeSolidity.ts var isRelative, isRelativeSolidity; var init_isRelativeSolidity = __esm({ "src/utils/isRelativeSolidity.ts"() { init_isSolidity(); isRelative = (fileName) => fileName.startsWith("./") || fileName.startsWith("../"); isRelativeSolidity = (fileName) => isRelative(fileName) && isSolidity(fileName); } }); var solidityModuleResolver; var init_solidityModuleResolver = __esm({ "src/utils/solidityModuleResolver.ts"() { init_isRelativeSolidity(); init_isSolidity(); solidityModuleResolver = (moduleName, ts, createInfo, containingFile) => { if (isRelativeSolidity(moduleName)) { return { extension: ts.Extension.Dts, isExternalLibraryImport: false, resolvedFileName: path__default.default.resolve(path__default.default.dirname(containingFile), moduleName) }; } if (isSolidity(moduleName)) { return { extension: ts.Extension.Dts, isExternalLibraryImport: false, resolvedFileName: module$1.createRequire(path__default.default.dirname(containingFile)).resolve(moduleName) }; } if (moduleName.startsWith("@tevm/contract")) { const result = ts.resolveModuleName( moduleName, containingFile, createInfo.project.getCompilerOptions(), createInfo.project ); if (result.resolvedModule) { return { extension: ts.Extension.Dts, isExternalLibraryImport: true, resolvedFileName: result.resolvedModule.resolvedFileName }; } console.error("Could not resolve module. Is tevm/core installed?", moduleName, result); return void 0; } return void 0; }; } }); // src/utils/findNode.ts function findNode(rootNode, position) { if (position < 0) { throw new Error("Position must be non-negative"); } if (Number.isInteger(position) === false) { throw new Error("Position must be an integer"); } let foundNode = null; function visit(node) { if (position >= node.getStart() && position <= node.getEnd()) { foundNode = node; node.forEachChild(visit); } } rootNode.forEachChild(visit); return foundNode; } var init_findNode = __esm({ "src/utils/findNode.ts"() { } }); // src/utils/invariant.ts function invariant(condition, message) { if (!condition) { throw new Error(message); } } var init_invariant = __esm({ "src/utils/invariant.ts"() { } }); function convertSolcAstToTsDefinitionInfo(astNode, fileName, containerName, solcInput, ts) { var _a; const [start, length] = astNode.src.split(":").map(Number); let kind = ts.ScriptElementKind.unknown; let name = "unknown"; if (astNode.nodeType === "VariableDeclaration") { kind = ts.ScriptElementKind.variableElement; name = astNode.name; } else if (astNode.nodeType === "FunctionDefinition") { kind = ts.ScriptElementKind.functionElement; name = astNode.name; } const inputLength = (_a = solcInput.sources[fileName].content) == null ? void 0 : _a.length; const actualLength = fs.readFileSync(fileName, "utf8").length; const offset = inputLength - actualLength; return { fileName, textSpan: ts.createTextSpan(start - offset, length), kind, name, containerKind: ts.ScriptElementKind.classElement, containerName }; } var init_convertSolcAstToTsDefinitionInfo = __esm({ "src/utils/convertSolcAstToTsDefinitionInfo.ts"() { } }); // src/utils/findContractDefinitionFileNameFromTevmNode.ts function findContractDefinitionFileNameFromTevmNode(node, languageService, fileName, ts) { let current = node; while (current) { if (!ts.isPropertyAccessExpression(current)) { current = current.parent; continue; } const parent = current.expression; if (!ts.isCallExpression(parent)) { current = current.parent; continue; } const grandParent = parent.expression; if (!ts.isPropertyAccessExpression(grandParent)) { current = current.parent; continue; } if (!["read", "write", "events"].includes(grandParent.name.getText())) { current = current.parent; continue; } const contractNode = grandParent.expression; const contractDefinition = languageService.getDefinitionAtPosition(fileName, contractNode.getStart()); if (!contractDefinition || contractDefinition.length === 0) { current = current.parent; continue; } const out = contractDefinition[0].fileName; if (!out.endsWith(".sol")) { current = current.parent; continue; } return out; } return null; } var init_findContractDefinitionFileNameFromTevmNode = __esm({ "src/utils/findContractDefinitionFileNameFromTevmNode.ts"() { } }); // src/utils/index.ts var init_utils = __esm({ "src/utils/index.ts"() { init_isRelativeSolidity(); init_isSolidity(); init_solidityModuleResolver(); init_findNode(); init_invariant(); init_convertSolcAstToTsDefinitionInfo(); init_findContractDefinitionFileNameFromTevmNode(); } }); var getDefinitionServiceDecorator; var init_getDefinitionAtPosition = __esm({ "src/decorators/getDefinitionAtPosition.ts"() { init_utils(); init_utils(); getDefinitionServiceDecorator = (service, config, logger, ts, fao, solcCache) => { const getDefinitionAtPosition = (fileName, position) => { var _a, _b; const definition = service.getDefinitionAtPosition(fileName, position); const sourceFile = (_a = service.getProgram()) == null ? void 0 : _a.getSourceFile(fileName); const node = sourceFile && findNode(sourceFile, position); const ContractPath = node && findContractDefinitionFileNameFromTevmNode(node, service, fileName, ts); if (!ContractPath) { return definition; } const plugin = baseBundler.bundler(config, logger, fao, solc__namespace, solcCache); const includedAst = true; const { asts, solcInput } = plugin.resolveDtsSync(ContractPath, process.cwd(), includedAst, false); if (!asts) { logger.error(`@tevm/ts-plugin: getDefinitionAtPositionDecorator was unable to resolve asts for ${ContractPath}`); return definition; } const definitions = []; for (const [fileName2, ast] of Object.entries(asts)) { for (const functionDef of utils_js.findAll("EventDefinition", ast)) { if (functionDef.name === (node == null ? void 0 : node.getText())) { definitions.push({ node: functionDef, fileName: fileName2 }); } } for (const functionDef of utils_js.findAll("FunctionDefinition", ast)) { if (functionDef.name === (node == null ? void 0 : node.getText())) { definitions.push({ node: functionDef, fileName: fileName2 }); } } } if (!definitions.length) { logger.error(`@tevm/ts-plugin: unable to find definitions ${ContractPath}`); return definition; } const contractName = ((_b = ContractPath.split("/").pop()) == null ? void 0 : _b.split(".")[0]) ?? "Contract"; return [ ...definitions.map( ({ fileName: fileName2, node: node2 }) => convertSolcAstToTsDefinitionInfo(node2, fileName2, contractName, solcInput, ts) ), ...definition ?? [] ]; }; const getDefinitionAndBoundSpan = (fileName, position) => { var _a; const definitions = getDefinitionAtPosition(fileName, position); if (!definitions) { return service.getDefinitionAndBoundSpan(fileName, position); } if (!definitions.some((definition) => definition.fileName.endsWith(".sol"))) { return service.getDefinitionAndBoundSpan(fileName, position); } const sourceFile = (_a = service.getProgram()) == null ? void 0 : _a.getSourceFile(fileName); const node = sourceFile && findNode(sourceFile, position); const textSpan = node ? ts.createTextSpanFromBounds(node.getStart(), node.getEnd()) : void 0; return { definitions, textSpan: textSpan ?? ts.createTextSpan(0, 0) // Fallback to a zero-length span }; }; return new Proxy(service, { get(target, key) { if (key === "getDefinitionAtPosition") { return getDefinitionAtPosition; } if (key === "getDefinitionAndBoundSpan") { return getDefinitionAndBoundSpan; } return target[key]; } }); }; } }); // src/factories/logger.ts var createLogger; var init_logger = __esm({ "src/factories/logger.ts"() { createLogger = (pluginCreateInfo) => { const info = (msg) => pluginCreateInfo.project.projectService.logger.info(`[tevm-ts-plugin] ${msg}`); const warn = (msg) => pluginCreateInfo.project.projectService.logger.info(`[tevm-ts-plugin] warning: ${msg}`); const error = (msg) => pluginCreateInfo.project.projectService.logger.info(`[tevm-ts-plugin] error: ${msg}`); const log = (msg) => pluginCreateInfo.project.projectService.logger.info(`[tevm-ts-plugin] log: ${msg}`); return { info, warn, error, log }; }; } }); // src/factories/decorator.ts var createHostDecorator, decorateHost; var init_decorator = __esm({ "src/factories/decorator.ts"() { createHostDecorator = (decorator) => { return (createInfo, ...rest) => { const proxy = decorator(createInfo, ...rest); return new Proxy(createInfo.languageServiceHost, { get(target, key) { if (key in proxy) { return proxy[key]; } return target[key]; } }); }; }; decorateHost = (...decorators) => { return (createInfo, ...rest) => { if (decorators.length === 0) { return createInfo.languageServiceHost; } const [nextDecorator, ...restDecorators] = decorators; const decoratedHost = nextDecorator(createInfo, ...rest); const decoratedCreateInfo = new Proxy(createInfo, { get(target, key) { if (key === "languageServiceHost") { return decoratedHost; } return target[key]; } }); return decorateHost(...restDecorators)(decoratedCreateInfo, ...rest); }; }; } }); // src/factories/index.ts var init_factories = __esm({ "src/factories/index.ts"() { init_logger(); init_decorator(); } }); // src/decorators/getScriptKind.ts var getScriptKindDecorator; var init_getScriptKind = __esm({ "src/decorators/getScriptKind.ts"() { init_factories(); init_utils(); getScriptKindDecorator = createHostDecorator((createInfo, ts, logger, config) => { return { getScriptKind: (fileName) => { if (isRelativeSolidity(fileName)) { return ts.ScriptKind.TS; } if (isSolidity(fileName)) { return ts.ScriptKind.External; } if (!createInfo.languageServiceHost.getScriptKind) { return ts.ScriptKind.Unknown; } return createInfo.languageServiceHost.getScriptKind(fileName); } }; }); } }); var resolveJsonAsConst; var init_resolveJsonAsConst = __esm({ "src/utils/resolveJsonAsConst.ts"() { resolveJsonAsConst = (config, jsonFilePath, fao, languageServiceHost, ts) => { for (const matcher of config.jsonAsConst) { if (minimatch.minimatch(jsonFilePath, matcher)) { const jsonString = fao.readFileSync(jsonFilePath, "utf8"); return ts.ScriptSnapshot.fromString(`export default ${jsonString} as const`); } } return languageServiceHost.getScriptSnapshot(jsonFilePath); }; } }); var getScriptSnapshotDecorator; var init_getScriptSnapshot = __esm({ "src/decorators/getScriptSnapshot.ts"() { init_factories(); init_utils(); init_resolveJsonAsConst(); getScriptSnapshotDecorator = (solcCache) => createHostDecorator(({ languageServiceHost }, ts, logger, config, fao) => { return { getScriptSnapshot: (filePath) => { if (filePath.endsWith(".json")) { return resolveJsonAsConst(config, filePath, fao, languageServiceHost, ts); } if (!isSolidity(filePath) || !fs.existsSync(filePath) || fs.existsSync(`${filePath}.d.ts`) || fs.existsSync(`${filePath}.ts`)) { return languageServiceHost.getScriptSnapshot(filePath); } try { const plugin = baseBundler.bundler(config, logger, fao, solc__namespace, solcCache); const resolveBytecode = filePath.endsWith(".s.sol"); const snapshot = plugin.resolveDtsSync(filePath, process.cwd(), false, resolveBytecode); if (config.debug) { fs.writeFileSync( `${filePath}.debug.d.ts`, `// Debug: the following snapshot is what tevm resolves ${filePath} to ${snapshot.code}` ); } return ts.ScriptSnapshot.fromString(snapshot.code); } catch (e) { logger.error(`@tevm/ts-plugin: getScriptSnapshotDecorator was unable to resolve dts for ${filePath}`); logger.error(e); return ts.ScriptSnapshot.fromString("export {}"); } } }; }); } }); // src/decorators/resolveModuleNameLiterals.ts var resolveModuleNameLiteralsDecorator; var init_resolveModuleNameLiterals = __esm({ "src/decorators/resolveModuleNameLiterals.ts"() { init_factories(); init_utils(); init_invariant(); resolveModuleNameLiteralsDecorator = createHostDecorator((createInfo, ts, logger, config) => { return { resolveModuleNameLiterals: (moduleNames, containingFile, ...rest) => { var _a, _b; const resolvedModules = (_b = (_a = createInfo.languageServiceHost).resolveModuleNameLiterals) == null ? void 0 : _b.call( _a, moduleNames, containingFile, ...rest ); return moduleNames.map(({ text: moduleName }, index) => { let remappedName = moduleName; Object.entries(config.remappings).forEach(([from, to]) => { if (moduleName.startsWith(from)) { remappedName = moduleName.replace(from, to); } }); invariant(resolvedModules, 'Expected "resolvedModules" to be defined.'); try { const resolvedModule = solidityModuleResolver(remappedName, ts, createInfo, containingFile); if (resolvedModule) { return { resolvedModule }; } return resolvedModules[index]; } catch (e) { logger.error(e); return resolvedModules[index]; } }); } }; }); } }); // src/decorators/index.ts var init_decorators = __esm({ "src/decorators/index.ts"() { init_getScriptKind(); init_getScriptSnapshot(); init_resolveModuleNameLiterals(); } }); var createFileAccessObject, createRealFileAccessObject; var init_fileAccessObject = __esm({ "src/factories/fileAccessObject.ts"() { createFileAccessObject = (lsHost) => { return { existsSync: (fileName) => lsHost.fileExists(fileName), readFileSync: (fileName, encoding) => { const file = lsHost.readFile(fileName, encoding); if (!file) { throw new Error(`@tevm/ts-plugin: unable to read file ${fileName}`); } return file; }, writeFileSync: (fileName, data) => { var _a; (_a = lsHost.writeFile) == null ? void 0 : _a.call(lsHost, fileName, data); }, // TODO clean this up. This works fine only because only the cache needs them and the cache is operating on a real file system and not a virtual one // These are just stubs to match interface since making multiple interfaces is tedious atm exists: async (fileName) => { return lsHost.fileExists(fileName); }, readFile: async (fileName, encoding) => { const file = lsHost.readFile(fileName, encoding); if (!file) { throw new Error(`@tevm/ts-plugin: unable to read file ${fileName}`); } return file; }, stat: promises.stat, statSync: fs.statSync, mkdirSync: fs.mkdirSync, mkdir: promises.mkdir, writeFile: promises.writeFile }; }; createRealFileAccessObject = () => { return { readFile: promises.readFile, existsSync: fs.existsSync, readFileSync: fs.readFileSync, writeFileSync: fs.writeFileSync, statSync: fs.statSync, stat: promises.stat, mkdirSync: fs.mkdirSync, mkdir: promises.mkdir, writeFile: promises.writeFile, exists: async (fileName) => { try { await promises.access(fileName); return true; } catch (e) { return false; } } }; }; } }); var tsPlugin; var init_tsPlugin = __esm({ "src/tsPlugin.ts"() { init_getDefinitionAtPosition(); init_decorators(); init_fileAccessObject(); init_factories(); init_utils(); tsPlugin = (modules) => { return { create: (createInfo) => { const logger = createLogger(createInfo); const config$1 = Effect.runSync( config.loadConfig(createInfo.project.getCurrentDirectory()).pipe( Effect.catchTag( "FailedToReadConfigError", () => Effect.logWarning("Unable to find tevm.config.json. Using default config.").pipe(Effect.map(() => config.defaultConfig)) ) ) ); const fao = createFileAccessObject(createInfo.languageServiceHost); const cache = bundlerCache.createCache( config$1.cacheDir, // this fao uses real file system // TODO we want to handle the case where fs doesn't exist createRealFileAccessObject(), createInfo.project.getCurrentDirectory() ); const service = getDefinitionServiceDecorator( modules.typescript.createLanguageService( decorateHost(getScriptKindDecorator, resolveModuleNameLiteralsDecorator, getScriptSnapshotDecorator(cache))( createInfo, modules.typescript, logger, config$1, fao ) ), config$1, logger, modules.typescript, fao, cache ); return service; }, getExternalFiles: (project) => { return project.getFileNames().filter(isSolidity); } }; }; } }); // src/index.ts var require_src = __commonJS({ "src/index.ts"(exports, module) { init_tsPlugin(); module.exports = tsPlugin; } }); var index = require_src(); module.exports = index; //# sourceMappingURL=index.cjs.map //# sourceMappingURL=index.cjs.map