Skip to content

Commit 600d6ad

Browse files
Merge pull request #726 from protofire/fix-natspec-enforce-on-internals
Fix natspec enforce on internals
2 parents c3d3ed7 + 3debb75 commit 600d6ad

File tree

3 files changed

+111
-7
lines changed

3 files changed

+111
-7
lines changed

docs/rules/best-practices/use-natspec.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ This rule accepts an array of options:
5757
```
5858

5959
### Notes
60+
- For `internal` or `private` function this rule checks natspec as configured, only if there are tags present. If not, function is skipped.
61+
- For `external` or `public` function this rule checks natspec as specified in the config.
6062
- If a function or return value has unnamed parameters (e.g. `function foo(uint256)`), the rule only checks the number of `@param` or `@return` tags, not their names.
6163
- If a function or variable has `@inheritdoc`, the rule skips the validation.
6264
- The rule supports both `///` and `/** */` style NatSpec comments.

lib/rules/best-practices/use-natspec.js

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,12 @@ const meta = {
202202
],
203203
},
204204
notes: [
205+
{
206+
note: 'For `internal` or `private` function this rule checks natspec as configured, only if there are tags present. If not, function is skipped.',
207+
},
208+
{
209+
note: 'For `external` or `public` function this rule checks natspec as specified in the config.',
210+
},
205211
{
206212
note: 'If a function or return value has unnamed parameters (e.g. `function foo(uint256)`), the rule only checks the number of `@param` or `@return` tags, not their names.',
207213
},
@@ -253,7 +259,7 @@ class UseNatspecChecker extends BaseChecker {
253259
if (!hasParameters(node)) tags.splice(tags.indexOf('param'), 1)
254260
if (!hasReturn(node)) tags.splice(tags.indexOf('return'), 1)
255261

256-
this.checkNode(node, 'function', tags, isPublicLike)
262+
this.checkNode(node, 'function', tags, isPublicLike, isPublicLike)
257263
}
258264

259265
EventDefinition(node) {
@@ -267,17 +273,24 @@ class UseNatspecChecker extends BaseChecker {
267273
this.checkNode(node, 'variable', NATSPEC_TARGETS.variable, true)
268274
}
269275

270-
checkNode(node, type, overrideTags, requireNoticeIfPublic = false) {
276+
checkNode(node, type, overrideTags, requireNoticeIfPublic, isPublicLike = false) {
271277
const name = node.name || (node.id && node.id.name) || '<anonymous>'
272278
const tagsRequired = overrideTags || NATSPEC_TARGETS[type] || []
273279
const startOffset = node.range[0]
274280
const comments = getLeadingNatSpecComments(startOffset, this.tokens)
275-
const tags = extractNatSpecTags(comments)
276281

277-
// console.log('\n>>> CHECKING', type, name)
278-
// console.log('COMMENTS:', comments)
279-
// console.log('TAGS:', tags)
282+
console.log('isPublicLike :>> ', isPublicLike)
283+
console.log('comments.length :>> ', comments.length)
284+
console.log('type :>> ', type)
285+
286+
// check the function is not publicLike and has no tags, avoid checking
287+
// if it is internal or private and has natspec comments, check them
288+
if (!isPublicLike && comments.length === 0 && type === 'function') return
289+
290+
// get the tags from comments
291+
const tags = extractNatSpecTags(comments)
280292

293+
// check the function is publicLike and has inheritdoc
281294
const hasInheritdoc = tags.includes('inheritdoc')
282295
if (requireNoticeIfPublic && hasInheritdoc) return
283296

@@ -369,7 +382,7 @@ function getLeadingNatSpecComments(startOffset, tokens) {
369382
comments.unshift(value)
370383
}
371384

372-
// Si encontramos código real (no comentario ni puntuación), cortamos
385+
// If there is real code (not comment or punctuation), break
373386
if (!value || (!value.startsWith('///') && !value.startsWith('/**'))) {
374387
if (token.type !== 'Punctuator') break
375388
}

test/rules/best-practices/use-natspec.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,5 +543,94 @@ describe('Linter - use-natspec', () => {
543543
"Mismatch in @return count for function 'doSomething'. Expected: 1, Found: 0"
544544
)
545545
})
546+
547+
it('should ignore internal and private functions if there are no tags', () => {
548+
const code = `
549+
contract HalfIgnored {
550+
551+
function doSomething1(uint256 amount) internal{}
552+
553+
function doSomething2(uint256 amount) private{}
554+
555+
/// @dev documented internal function
556+
function doSomething2(uint256 amount) private{}
557+
}
558+
`
559+
560+
const report = linter.processStr(code, {
561+
rules: {
562+
'use-natspec': [
563+
'error',
564+
{
565+
title: {
566+
enabled: false,
567+
},
568+
author: {
569+
enabled: false,
570+
},
571+
notice: {
572+
enabled: true,
573+
ignore: {
574+
contract: ['HalfIgnored'],
575+
},
576+
},
577+
param: {
578+
enabled: true,
579+
},
580+
},
581+
],
582+
},
583+
})
584+
assertNoErrors(report)
585+
})
586+
587+
it('should check internal and private functions if there are tags', () => {
588+
const code = `
589+
contract HalfIgnored {
590+
591+
/// @notice does something
592+
/// @param amount1 the amount
593+
function doSomething1(uint256 amount) internal returns(uint256){}
594+
}
595+
`
596+
597+
const report = linter.processStr(code, {
598+
rules: {
599+
'use-natspec': [
600+
'error',
601+
{
602+
title: {
603+
enabled: false,
604+
},
605+
author: {
606+
enabled: false,
607+
},
608+
notice: {
609+
enabled: true,
610+
ignore: {
611+
contract: ['HalfIgnored'],
612+
},
613+
},
614+
param: {
615+
enabled: true,
616+
},
617+
return: {
618+
enabled: true,
619+
},
620+
},
621+
],
622+
},
623+
})
624+
assertErrorCount(report, 3)
625+
assert.ok(
626+
report.reports[0].message,
627+
"Mismatch in @param names for function 'doSomething1'. Expected: [amount], Found: [amount1]"
628+
)
629+
assert.ok(report.reports[1].message, "Missing @return tag in function 'doSomething1'")
630+
assert.ok(
631+
report.reports[2].message,
632+
"Mismatch in @return count for function 'doSomething'. Expected: 1, Found: 0"
633+
)
634+
})
546635
})
547636
})

0 commit comments

Comments
 (0)