Skip to content

Commit

Permalink
feat: contract-level natspec
Browse files Browse the repository at this point in the history
  • Loading branch information
dristpunk committed Feb 14, 2024
1 parent 607a8ed commit 3c31976
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ function getArguments(): Config {
description: 'True if constructor natspec is mandatory.',
default: false,
},
contractNatspec: {
type: 'boolean',
description: 'True if contract natspec is mandatory.',
default: false,
},
})
.config()
.default('config', 'natspec-smells.config')
Expand Down
1 change: 1 addition & 0 deletions src/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export class Processor {

selectEligibleNodes(contract: ContractDefinition): NodeToProcess[] {
return [
contract,
...contract.vEnums,
...contract.vErrors,
...contract.vEvents,
Expand Down
3 changes: 3 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
ContractDefinition,
EnumDefinition,
ErrorDefinition,
EventDefinition,
Expand All @@ -14,6 +15,7 @@ export interface Config {
root: string; // Optional: Project root directory.
enforceInheritdoc: boolean; // Optional: True if all external and public functions should have @inheritdoc.
constructorNatspec: boolean; // Optional: True if the constructor should have natspec.
contractNatspec: boolean; // Optional: True if the contract should have natspec.
}

export interface NatspecDefinition {
Expand Down Expand Up @@ -42,6 +44,7 @@ export interface ASTNodeRaw {
}

export type NodeToProcess =
| ContractDefinition
| FunctionDefinition
| EnumDefinition
| ErrorDefinition
Expand Down
21 changes: 21 additions & 0 deletions src/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export class Validator {
}

validate(node: NodeToProcess, natspec: Natspec): string[] {
// Proccess contract-level natspec
if (node instanceof ContractDefinition) {
return this.config.contractNatspec ? this.validateContractNatspec(node, natspec) : [];
}

// Ignore fallback and receive
if (matchesFunctionKind(node, 'receive') || matchesFunctionKind(node, 'fallback')) {
return [];
Expand Down Expand Up @@ -133,4 +138,20 @@ export class Validator {

return _requiresInheritdoc;
}

/**
* Validate the natspec of a contract
* @param {ContractDefinition} node - The contract node
* @param {Natspec} natspec - The natspec of the contract
* @returns {string[]} - The list of alerts
*/
private validateContractNatspec(node: ContractDefinition, natspec: Natspec): string[] {
let alerts: string[] = [];

if (!natspec.tags.map((t) => t.name).includes('notice')) {
alerts.push(`Contract @notice is missing`);
}

return alerts;
}
}
23 changes: 23 additions & 0 deletions test/validator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,4 +311,27 @@ describe('Validator', () => {
expect(result).toContainEqual(`@inheritdoc is missing`);
});
});

describe('proccess contract-level natspec', () => {
it('should ignore missing natspec for a contract if disabled (by default)', () => {
node = contract;
const result = validator.validate(node, mockNatspec({}));
expect(result).toEqual([]);
});

it('should reveal missing natspec for a contract if enabled', () => {
const newValidator = new Validator(mockConfig({ contractNatspec: true }));
node = contract;
const result = newValidator.validate(node, mockNatspec({}));
expect(result).toContainEqual(`Contract @notice is missing`);
});

it('should pay attention only to the @notice tag', () => {
const newValidator = new Validator(mockConfig({ contractNatspec: true }));
node = contract;
const result = newValidator.validate(node, mockNatspec({ tags: [{ name: 'author', content: 'Some author' }] }));
expect(result).toContainEqual(`Contract @notice is missing`);
expect(result.length).toBe(1);
});
});
});

0 comments on commit 3c31976

Please sign in to comment.