Skip to content

Commit a1215b6

Browse files
committed
implement full support for circular dependencies
1 parent 774bd13 commit a1215b6

File tree

1 file changed

+10
-20
lines changed

1 file changed

+10
-20
lines changed

src/utils/scope.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,41 @@
11
import { ContractDefinition, SourceUnit } from "solidity-ast";
22
import { findAll } from "solidity-ast/utils";
33
import { DocItemWithContext } from "../site";
4+
import { mapValues } from './map-values';
45

56
export function getContractsInScope(item: DocItemWithContext) {
6-
const cache = new WeakMap<SourceUnit, Record<string, ContractDefinition>>();
7-
return run(item.__item_context.file);
7+
const cache = new WeakMap<SourceUnit, Record<string, () => ContractDefinition>>();
8+
return mapValues(run(item.__item_context.file), fn => fn());
89

910
function run(
1011
file: SourceUnit,
11-
stack = new Set<SourceUnit>(),
1212
aliasedImport = false,
13-
): Record<string, ContractDefinition> {
14-
if (stack.has(file)) {
15-
if (aliasedImport) {
16-
throw new Error('Circular dependency detected: aliased imports not supported');
17-
} else {
18-
return {};
19-
}
20-
}
21-
13+
): Record<string, () => ContractDefinition> {
2214
if (cache.has(file)) {
2315
return cache.get(file)!;
2416
}
2517

26-
stack.add(file);
18+
const scope: Record<string, () => ContractDefinition> = {};
2719

28-
const scope: Record<string, ContractDefinition> = {};
20+
cache.set(file, scope);
2921

3022
for (const c of findAll('ContractDefinition', file)) {
31-
scope[c.name] = c;
23+
scope[c.name] = () => c;
3224
}
3325

3426
for (const i of findAll('ImportDirective', file)) {
3527
const importedFile = item.__item_context.build.deref('SourceUnit', i.sourceUnit);
36-
const importedScope = run(importedFile, stack, aliasedImport || i.symbolAliases.length > 0);
28+
const importedScope = run(importedFile, aliasedImport || i.symbolAliases.length > 0);
3729
if (i.symbolAliases.length === 0) {
3830
Object.assign(scope, importedScope);
3931
} else {
4032
for (const a of i.symbolAliases) {
41-
scope[a.local ?? a.foreign.name] = importedScope[a.foreign.name]!;
33+
// Delayed function call supports circular dependencies
34+
scope[a.local ?? a.foreign.name] = importedScope[a.foreign.name] ?? (() => importedScope[a.foreign.name]!());
4235
}
4336
}
4437
};
4538

46-
stack.delete(file);
47-
48-
cache.set(file, scope);
4939
return scope;
5040
}
5141
}

0 commit comments

Comments
 (0)