Skip to content

Commit b75d0c2

Browse files
committed
fix: storage diagrams that have chained imports
1 parent bf9ce4e commit b75d0c2

File tree

7 files changed

+76
-24
lines changed

7 files changed

+76
-24
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,5 @@ sol2uml uses [@solidity-parser/parser](https://github.com/solidity-parser/parser
373373
The [Solidity language grammar](https://solidity.readthedocs.io/en/develop/miscellaneous.html#language-grammar) is published with each major release.
374374

375375
The diagrams are generated using [viz.js](https://github.com/mdaines/viz.js/) which uses [Graphviz](http://www.graphviz.org/) to render a [Scalable Vector Graphics (SVG)](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics) file. [Graphviz Online](https://dreampuf.github.io/GraphvizOnline/) allows dot files to be edited and rendered into a SVG dynamically.
376+
377+
The `diff` command use's Google's [Diff Match and Patch library](https://github.com/google/diff-match-patch).

lib/associations.js

Lines changed: 22 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/contracts/chainedImports/Base.sol

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,8 @@ pragma solidity ^0.8.17;
44
contract Base {
55
uint256 public baseNum;
66
}
7+
8+
contract BaseAliased {
9+
address public baseAddress;
10+
bool isAlias;
11+
}

src/contracts/chainedImports/BaseImport.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.17;
33

4-
import { Base } from "./Base.sol";
4+
import { Base, BaseAliased } from "./Base.sol";
55

66
contract Transient {
77
uint256 public transNum;
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.17;
33

4-
import { Base } from "./BaseImport.sol";
4+
import {Base, BaseAliased as Base2} from './BaseImport.sol';
55

6-
contract Concrete is Base {
6+
contract Concrete is Base, Base2 {
77
uint256 public concreteNum;
88
}

src/ts/associations.ts

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const findAssociatedClass = (
2727
// Could not find a link so now need to recursively look at imports of imports
2828
// add to already recursively processed files to avoid getting stuck in circular imports
2929
searchedAbsolutePaths.push(sourceUmlClass.absolutePath)
30-
return findImplicitImport(
30+
return findChainedImport(
3131
association,
3232
sourceUmlClass,
3333
umlClasses,
@@ -40,17 +40,17 @@ const isAssociated = (
4040
association: Association,
4141
sourceUmlClass: UmlClass,
4242
targetUmlClass: UmlClass,
43-
targetParentmlClass: UmlClass,
43+
targetParentUmlClass: UmlClass,
4444
): boolean => {
4545
if (association.parentUmlClassName) {
4646
return (
4747
// class is in the same source file
4848
(association.targetUmlClassName === targetUmlClass.name &&
49-
association.parentUmlClassName === targetParentmlClass?.name &&
49+
association.parentUmlClassName === targetParentUmlClass?.name &&
5050
sourceUmlClass.absolutePath === targetUmlClass.absolutePath) ||
5151
// imported classes with no explicit import names
5252
(association.targetUmlClassName === targetUmlClass.name &&
53-
association.parentUmlClassName === targetParentmlClass?.name &&
53+
association.parentUmlClassName === targetParentUmlClass?.name &&
5454
sourceUmlClass.imports.some(
5555
(i) =>
5656
i.absolutePath === targetUmlClass.absolutePath &&
@@ -110,18 +110,26 @@ const isAssociated = (
110110
)
111111
}
112112

113-
const findImplicitImport = (
113+
const findChainedImport = (
114114
association: Association,
115115
sourceUmlClass: UmlClass,
116116
umlClasses: readonly UmlClass[],
117117
searchedRelativePaths: string[],
118118
): UmlClass | undefined => {
119-
// Get all implicit imports. That is, imports that do not explicitly import contracts or interfaces.
120-
const implicitImports = sourceUmlClass.imports.filter(
121-
(i) => i.classNames.length === 0,
119+
// Get all valid imports. That is, imports that do not explicitly import contracts or interfaces
120+
// or explicitly import the source class
121+
const imports = sourceUmlClass.imports.filter(
122+
(i) =>
123+
i.classNames.length === 0 ||
124+
i.classNames.some(
125+
(cn) =>
126+
(association.targetUmlClassName === cn.className &&
127+
!cn.alias) ||
128+
association.targetUmlClassName === cn.alias,
129+
),
122130
)
123-
// For each implicit import
124-
for (const importDetail of implicitImports) {
131+
// For each import
132+
for (const importDetail of imports) {
125133
// Find a class with the same absolute path as the import so we can get the new imports
126134
const newSourceUmlClass = umlClasses.find(
127135
(c) => c.absolutePath === importDetail.absolutePath,
@@ -135,14 +143,28 @@ const findImplicitImport = (
135143
// Have already recursively looked for imports of imports in this file
136144
continue
137145
}
138-
// TODO need to handle imports that use aliases as the association will not be found
146+
147+
// find class linked to the association without aliased imports
139148
const umlClass = findAssociatedClass(
140149
association,
141150
newSourceUmlClass,
142151
umlClasses,
143152
searchedRelativePaths,
144153
)
145154
if (umlClass) return umlClass
155+
156+
// find all aliased imports
157+
const aliasedImports = importDetail.classNames.filter((cn) => cn.alias)
158+
// For each aliased import
159+
for (const aliasedImport of aliasedImports) {
160+
const umlClass = findAssociatedClass(
161+
{ ...association, targetUmlClassName: aliasedImport.className },
162+
newSourceUmlClass,
163+
umlClasses,
164+
searchedRelativePaths,
165+
)
166+
if (umlClass) return umlClass
167+
}
146168
}
147169
return undefined
148170
}

tests/tests.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,13 @@ sol2uml storage 0x2fdfbb2b905484f1445e23a97c97f65fe0e43dec -d -s 0xc0f42f73b8f01
176176
sol2uml storage 0x2fdfbb2b905484f1445e23a97c97f65fe0e43dec -d -s 0xc0f42f73b8f01849a2dd99753524d4ba14317eb3 \
177177
--slotNames OUSD.governor,OUSD.pending.governor,OUSD.reentry.status,0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
178178

179+
## From issue https://github.com/naddison36/sol2uml/issues/175
180+
sol2uml storage 0x8115366Ca7Cf280a760f0bC0F6Db3026e2437115 -v --data --storage 0xC13e21B648A5Ee794902342038FF3aDAB66BE987
181+
sol2uml storage 0x8115366Ca7Cf280a760f0bC0F6Db3026e2437115 -v --data --storage 0xC13e21B648A5Ee794902342038FF3aDAB66BE987 --hideExpand ______gap --hideValues
182+
183+
# Test import of imports including aliased imports
184+
sol2uml storage -v -c Concrete ../src/contracts/chainedImports
185+
179186
# Class
180187

181188
## Maker DSR Strategy Implementation
@@ -190,3 +197,7 @@ sol2uml ../src/contracts -b TestStorage -v
190197
sol2uml 0xCF205808Ed36593aa40a44F10c7f7C2F67d4A4d4 -v --network base
191198
## USDC on Base
192199
sol2uml 0x1833C6171E0A3389B156eAedB301CFfbf328B463 -v --network base
200+
201+
# All OpenZeppelin contracts
202+
sol2uml ../node_modules/@openzeppelin/contracts
203+

0 commit comments

Comments
 (0)