@@ -3,6 +3,7 @@ import { Node } from 'solidity-ast/node';
33import { SolcInput , SolcOutput } from '../solc-api' ;
44import { getStorageLocationAnnotation } from '../storage/namespace' ;
55import { assert } from './assert' ;
6+ import { FunctionDefinition } from 'solidity-ast' ;
67
78const OUTPUT_SELECTION = {
89 '*' : {
@@ -40,7 +41,6 @@ export function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcI
4041
4142 const orig = Buffer . from ( source . content , 'utf8' ) ;
4243
43- const replacedIdentifiers = new Set < string > ( ) ;
4444 const modifications : Modification [ ] = [ ] ;
4545
4646 for ( const node of output . sources [ sourcePath ] . ast . nodes ) {
@@ -60,6 +60,10 @@ export function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcI
6060 const contractNodes = contractDef . nodes ;
6161 for ( const contractNode of contractNodes ) {
6262 switch ( contractNode . nodeType ) {
63+ case 'FunctionDefinition' : {
64+ replaceFunction ( contractNode , orig , modifications ) ;
65+ break ;
66+ }
6367 case 'VariableDeclaration' : {
6468 // If variable is a constant, keep it since it may be referenced in a struct
6569 if ( contractNode . constant ) {
@@ -69,7 +73,6 @@ export function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcI
6973 }
7074 case 'ErrorDefinition' :
7175 case 'EventDefinition' :
72- case 'FunctionDefinition' :
7376 case 'ModifierDefinition' :
7477 case 'UsingForDirective' : {
7578 // Replace with an enum based on astId (the original name is not needed, since nothing should reference it)
@@ -100,27 +103,30 @@ export function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcI
100103 break ;
101104 }
102105
103- // - UsingForDirective isn't needed, but it might have NatSpec documentation which is not included in the AST.
104- // We convert it to a dummy enum to avoid orphaning any possible documentation.
105- // - ErrorDefinition, FunctionDefinition, and VariableDeclaration might be imported by other files, so they cannot be deleted.
106+ case 'FunctionDefinition' : {
107+ replaceFunction ( node , orig , modifications ) ;
108+ break ;
109+ }
110+
111+ // - VariableDeclaration and ErrorDefinition might be imported by other files, so they cannot be deleted.
106112 // However, we need to remove their values to avoid referencing other deleted nodes.
107- // We do this by converting them to dummy enums, but avoiding duplicate names.
108- case 'UsingForDirective' :
109- case 'ErrorDefinition' :
110- case 'FunctionDefinition' :
113+ // We do this by converting them to dummy enums with the same name.
111114 case 'VariableDeclaration' : {
112- // If an identifier with the same name was not previously written, replace with a dummy enum using its name.
113- // Otherwise replace with an enum based on astId to avoid duplicate names, which can happen if there was overloading.
114- // This does not need to check all identifiers from the original contract, since the original compilation
115- // should have failed if there were conflicts in the first place.
116- if ( 'name' in node && ! replacedIdentifiers . has ( node . name ) ) {
117- modifications . push ( makeReplace ( node , orig , toDummyEnumWithName ( node . name ) ) ) ;
118- replacedIdentifiers . add ( node . name ) ;
119- } else {
120- modifications . push ( makeReplace ( node , orig , toDummyEnumWithAstId ( node . id ) ) ) ;
115+ // If variable is a constant, keep it since it may be referenced in a struct
116+ if ( node . constant ) {
117+ break ;
121118 }
119+ // Otherwise, fall through to convert to dummy enum
120+ }
121+ case 'ErrorDefinition' : {
122+ modifications . push ( makeReplace ( node , orig , toDummyEnumWithName ( node . name ) ) ) ;
122123 break ;
123124 }
125+ // - UsingForDirective isn't needed, but it might have NatSpec documentation which is not included in the AST.
126+ // We convert it to a dummy enum to avoid orphaning any possible documentation.
127+ case 'UsingForDirective' :
128+ modifications . push ( makeReplace ( node , orig , toDummyEnumWithAstId ( node . id ) ) ) ;
129+ break ;
124130 case 'EnumDefinition' :
125131 case 'ImportDirective' :
126132 case 'PragmaDirective' :
@@ -158,6 +164,26 @@ function toDummyEnumWithAstId(astId: number) {
158164 return `enum $astId_${ astId } _${ ( Math . random ( ) * 1e6 ) . toFixed ( 0 ) } { dummy }` ;
159165}
160166
167+ function replaceFunction ( node : FunctionDefinition , orig : Buffer , modifications : Modification [ ] ) {
168+ if ( node . kind === 'constructor' ) {
169+ modifications . push ( makeDelete ( node , orig ) ) ;
170+ } else {
171+ if ( node . modifiers . length > 0 ) {
172+ for ( const modifier of node . modifiers ) {
173+ modifications . push ( makeDelete ( modifier , orig ) ) ;
174+ }
175+ }
176+
177+ if ( node . returnParameters . parameters . length > 0 ) {
178+ modifications . push ( makeReplace ( node . returnParameters , orig , '(bool)' ) ) ;
179+ }
180+
181+ if ( node . body ) {
182+ modifications . push ( makeReplace ( node . body , orig , '{}' ) ) ;
183+ }
184+ }
185+ }
186+
161187function getPositions ( node : Node ) {
162188 const [ start , length ] = node . src . split ( ':' ) . map ( Number ) ;
163189 const end = start + length ;
0 commit comments