Skip to content

Commit

Permalink
fix handling of circular dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
frangio committed Oct 5, 2021
1 parent eb41e4b commit fbfc088
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.5.16

- Change handling of circular dependencies to an incomplete but correct approach, fixing a potential issue with bad caching.

## 0.5.15

- Fix use of `@inheritdoc` in circularly dependent files.
Expand Down
28 changes: 19 additions & 9 deletions src/source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class SourceFile {
);
}

@memoize
get contractsInScope(): Record<string, SourceContract> {
return contractsInScope(this);
}
Expand All @@ -78,16 +79,22 @@ class SourceFile {
}
}

const scopeCache = new WeakMap<SourceFile, Record<string, SourceContract>>();

function contractsInScope(file: SourceFile): Record<string, SourceContract> {
if (scopeCache.has(file)) {
return scopeCache.get(file)!;
function contractsInScope(
file: SourceFile,
stack = new Set<SourceFile>(),
aliasedImport = false,
): Record<string, SourceContract> {
if (stack.has(file)) {
if (aliasedImport) {
throw new Error('Circular dependency detected: aliased imports not supported');
} else {
return {};
}
}

const scope: Record<string, SourceContract> = {};
stack.add(file);

scopeCache.set(file, scope);
const scope: Record<string, SourceContract> = {};

for (const c of file.contracts) {
scope[c.name] = c;
Expand All @@ -96,15 +103,18 @@ function contractsInScope(file: SourceFile): Record<string, SourceContract> {
const imports = file.ast.nodes.filter(isImportDirective);
for (const i of imports) {
const importedFile = file.source.fileById(i.sourceUnit);
const importedScope = contractsInScope(importedFile, stack, aliasedImport || i.symbolAliases.length > 0);
if (i.symbolAliases.length === 0) {
Object.assign(scope, importedFile.contractsInScope);
Object.assign(scope, importedScope);
} else {
for (const a of i.symbolAliases) {
scope[a.local ?? a.foreign.name] = importedFile.contractsInScope[a.foreign.name];
scope[a.local ?? a.foreign.name] = importedScope[a.foreign.name];
}
}
};

stack.delete(file);

return scope;
}

Expand Down

0 comments on commit fbfc088

Please sign in to comment.