@@ -393,6 +393,30 @@ export class Parser {
393393 }
394394 }
395395
396+ findModifierDefinitionByContractName ( node : ModifierDefinition , contractName : string ) : ModifierDefinition | undefined {
397+ // Since we cannot access the scope (Contract) in which the modifier is defined,
398+ // we are looking for the topmost parent modifier documentation without the @inheritdoc tag.
399+ const inheritDocsRegex = / @ i n h e r i t d o c ( \w + ) / gm;
400+ const matches = inheritDocsRegex . exec ( node . documentation ?. text ! ) ;
401+
402+ if ( ! matches ) {
403+ return node as ModifierDefinition ;
404+ }
405+
406+ if ( ! node . baseModifiers ) {
407+ return undefined ;
408+ }
409+
410+ for ( let i = 0 ; i < node . baseModifiers . length ; i ++ ) {
411+ const baseModifier = this . deref ( "ModifierDefinition" , node . baseModifiers [ i ] ) ;
412+ const result = this . findModifierDefinitionByContractName ( baseModifier , contractName ) ;
413+
414+ if ( result ) {
415+ return result ;
416+ }
417+ }
418+ }
419+
396420 parseNameAndDescription ( text : string ) : [ name : string , description : string ] {
397421 const nameAndDescriptionRegex = / ^ ( \w + ) .? ( [ \s \S ] * ) ? / gm;
398422 const matches = nameAndDescriptionRegex . exec ( text ) ;
@@ -556,7 +580,13 @@ export class Parser {
556580 }
557581
558582 const [ , parentName ] = matches ;
559- const parentNode = this . findFunctionDefinitionByContractName ( node , parentName ) ;
583+
584+ let parentNode ;
585+ if ( node . nodeType === "FunctionDefinition" ) {
586+ parentNode = this . findFunctionDefinitionByContractName ( node , parentName ) ;
587+ } else if ( node . nodeType === "ModifierDefinition" ) {
588+ parentNode = this . findModifierDefinitionByContractName ( node , parentName ) ;
589+ }
560590
561591 if ( ! parentNode ) {
562592 throw new Error ( `Invalid inheritdoc tag: ${ text } ` ) ;
0 commit comments