@@ -5,6 +5,7 @@ import path from "node:path";
55import { findContractNode } from "./findContractNode" ;
66import { QualifiedSymbol } from "./contractToInterface" ;
77import { findSymbolImport } from "./findSymbolImport" ;
8+ import { resolveRemapping } from "./resolveRemapping" ;
89
910interface InheritanceInfo {
1011 baseContracts : string [ ] ;
@@ -22,17 +23,20 @@ interface InheritanceInfo {
2223export async function createInheritanceResolver (
2324 contractPath : string ,
2425 contractName : string ,
26+ rootDir : string ,
27+ remappings : string [ ] = [ ] ,
2528) : Promise < ( symbol : string ) => QualifiedSymbol | undefined > {
2629 const resolvedContracts = new Map < string , InheritanceInfo > ( ) ;
2730 const visitedPaths = new Set < string > ( ) ;
2831
2932 async function parseContract ( filePath : string , targetContractName ?: string ) : Promise < InheritanceInfo | undefined > {
3033 // Prevent infinite recursion
3134 const normalizedPath = path . resolve ( filePath ) ;
32- if ( visitedPaths . has ( normalizedPath ) ) {
35+ const visitKey = targetContractName ? `${ normalizedPath } :${ targetContractName } ` : normalizedPath ;
36+ if ( visitedPaths . has ( visitKey ) ) {
3337 return undefined ;
3438 }
35- visitedPaths . add ( normalizedPath ) ;
39+ visitedPaths . add ( visitKey ) ;
3640
3741 try {
3842 const source = await readFile ( filePath , "utf8" ) ;
@@ -80,7 +84,7 @@ export async function createInheritanceResolver(
8084 }
8185 }
8286
83- // Extract symbols defined in this contract
87+ // Extract symbols defined in this contract/interface
8488 visit ( contractNode , {
8589 StructDefinition ( node ) {
8690 if ( node . name ) {
@@ -109,11 +113,11 @@ export async function createInheritanceResolver(
109113 // Store the original import path
110114 info . baseContractImports . set ( baseName , importInfo . path ) ;
111115
112- const importPath = importInfo . path . startsWith ( "." )
116+ const resolvedPath = importInfo . path . startsWith ( "." )
113117 ? path . resolve ( path . dirname ( filePath ) , importInfo . path )
114- : importInfo . path ;
118+ : resolveRemapping ( importInfo . path , remappings , rootDir ) ;
115119
116- await parseContract ( importPath , baseName ) ;
120+ await parseContract ( resolvedPath , baseName ) ;
117121 }
118122 }
119123 }
@@ -157,8 +161,24 @@ export async function createInheritanceResolver(
157161 const baseInfo = resolvedContracts . get ( baseName ) ;
158162 if ( baseInfo ?. symbols . has ( symbol ) ) {
159163 // Found the symbol in a base contract
160- // Get the import path from the main contract to this base contract
161- const importPath = mainInfo ?. baseContractImports . get ( baseName ) || `./${ baseName } .sol` ;
164+ // Find the import path for this base contract
165+ let importPath : string | undefined ;
166+
167+ for ( const [ , info ] of resolvedContracts ) {
168+ const baseImportPath = info . baseContractImports . get ( baseName ) ;
169+ if ( baseImportPath ) {
170+ importPath = baseImportPath ;
171+ break ;
172+ }
173+ }
174+
175+ // If we still don't have an import path, throw an error
176+ if ( ! importPath ) {
177+ throw new Error (
178+ `Could not find import path for base contract "${ baseName } " which defines "${ symbol } ". ` +
179+ `Make sure "${ baseName } " is properly imported in your contract or its dependencies.` ,
180+ ) ;
181+ }
162182
163183 return {
164184 symbol,
0 commit comments