Skip to content

Commit

Permalink
Merge pull request #557 from protofire/interface-starts-with-i
Browse files Browse the repository at this point in the history
New Rule: Interface starts with i
  • Loading branch information
dbale-altoros authored Mar 11, 2024
2 parents c0c6696 + 06754b5 commit 10aa9f8
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 23 deletions.
1 change: 1 addition & 0 deletions conf/rulesets/solhint-all.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module.exports = Object.freeze({
'code-complexity': ['warn', 7],
'explicit-types': ['warn', 'explicit'],
'function-max-lines': ['warn', 50],
'interface-starts-with-i': 'warning',
'max-line-length': ['error', 120],
'max-states-count': ['warn', 15],
'no-console': 'error',
Expand Down
47 changes: 24 additions & 23 deletions docs/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,30 @@ title: "Rule Index of Solhint"
| [constructor-syntax](./rules/best-practises/constructor-syntax.md) | Constructors should use the new constructor keyword. | | |

## Style Guide Rules

| Rule Id | Error | Recommended | Deprecated |
| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | ------------ | ----------- |
| [interface-starts-with-i](./rules/naming/interface-starts-with-i.md) | Solidity Interfaces names should start with an `I` | | |
| [const-name-snakecase](./rules/naming/const-name-snakecase.md) | Constant name must be in capitalized SNAKE_CASE. (Does not check IMMUTABLES, use immutable-vars-naming) | $~~~~~~~~$✔️ | |
| [contract-name-camelcase](./rules/naming/contract-name-camelcase.md) | Contract, Structs and Enums should be in CamelCase. | $~~~~~~~~$✔️ | |
| [event-name-camelcase](./rules/naming/event-name-camelcase.md) | Event name must be in CamelCase. | $~~~~~~~~$✔️ | |
| [foundry-test-functions](./rules/naming/foundry-test-functions.md) | Enforce naming convention on functions for Foundry test cases | | |
| [func-name-mixedcase](./rules/naming/func-name-mixedcase.md) | Function name must be in mixedCase. | $~~~~~~~~$✔️ | |
| [func-named-parameters](./rules/naming/func-named-parameters.md) | Enforce named parameters for function calls with 4 or more arguments. This rule may have some false positives | | |
| [func-param-name-mixedcase](./rules/naming/func-param-name-mixedcase.md) | Function param name must be in mixedCase. | | |
| [immutable-vars-naming](./rules/naming/immutable-vars-naming.md) | Check Immutable variables. Capitalized SNAKE_CASE or mixedCase depending on configuration. | $~~~~~~~~$✔️ | |
| [modifier-name-mixedcase](./rules/naming/modifier-name-mixedcase.md) | Modifier name must be in mixedCase. | | |
| [named-parameters-mapping](./rules/naming/named-parameters-mapping.md) | Solidity v0.8.18 introduced named parameters on the mappings definition. | | |
| [private-vars-leading-underscore](./rules/naming/private-vars-leading-underscore.md) | Non-external functions and state variables should start with a single underscore. Others, shouldn't | | |
| [use-forbidden-name](./rules/naming/use-forbidden-name.md) | Avoid to use letters 'I', 'l', 'O' as identifiers. | $~~~~~~~~$✔️ | |
| [var-name-mixedcase](./rules/naming/var-name-mixedcase.md) | Variable name must be in mixedCase. (Does not check IMMUTABLES, use immutable-vars-naming) | $~~~~~~~~$✔️ | |
| [func-order](./rules/order/func-order.md) | Function order is incorrect. | | $~~~~~~~$✔️ |
| [imports-on-top](./rules/order/imports-on-top.md) | Import statements must be on top. | $~~~~~~~~$✔️ | |
| [ordering](./rules/order/ordering.md) | Check order of elements in file and inside each contract, according to the style guide. | | |
| [visibility-modifier-order](./rules/order/visibility-modifier-order.md) | Visibility modifier must be first in list of modifiers. | $~~~~~~~~$✔️ | |

## Gas Consumption Rules

| Rule Id | Error | Recommended | Deprecated |
Expand All @@ -48,29 +72,6 @@ title: "Rule Index of Solhint"
| [quotes](./rules/miscellaneous/quotes.md) | Enforces the use of double or simple quotes as configured for string literals. Values must be 'single' or 'double'. | $~~~~~~~~$✔️ | |

## Style Guide Rules

| Rule Id | Error | Recommended | Deprecated |
| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | ------------ | ----------- |
| [const-name-snakecase](./rules/naming/const-name-snakecase.md) | Constant name must be in capitalized SNAKE_CASE. (Does not check IMMUTABLES, use immutable-vars-naming) | $~~~~~~~~$✔️ | |
| [contract-name-camelcase](./rules/naming/contract-name-camelcase.md) | Contract, Structs and Enums should be in CamelCase. | $~~~~~~~~$✔️ | |
| [event-name-camelcase](./rules/naming/event-name-camelcase.md) | Event name must be in CamelCase. | $~~~~~~~~$✔️ | |
| [foundry-test-functions](./rules/naming/foundry-test-functions.md) | Enforce naming convention on functions for Foundry test cases | | |
| [func-name-mixedcase](./rules/naming/func-name-mixedcase.md) | Function name must be in mixedCase. | $~~~~~~~~$✔️ | |
| [func-named-parameters](./rules/naming/func-named-parameters.md) | Enforce named parameters for function calls with 4 or more arguments. This rule may have some false positives | | |
| [func-param-name-mixedcase](./rules/naming/func-param-name-mixedcase.md) | Function param name must be in mixedCase. | | |
| [immutable-vars-naming](./rules/naming/immutable-vars-naming.md) | Check Immutable variables. Capitalized SNAKE_CASE or mixedCase depending on configuration. | $~~~~~~~~$✔️ | |
| [modifier-name-mixedcase](./rules/naming/modifier-name-mixedcase.md) | Modifier name must be in mixedCase. | | |
| [named-parameters-mapping](./rules/naming/named-parameters-mapping.md) | Solidity v0.8.18 introduced named parameters on the mappings definition. | | |
| [private-vars-leading-underscore](./rules/naming/private-vars-leading-underscore.md) | Non-external functions and state variables should start with a single underscore. Others, shouldn't | | |
| [use-forbidden-name](./rules/naming/use-forbidden-name.md) | Avoid to use letters 'I', 'l', 'O' as identifiers. | $~~~~~~~~$✔️ | |
| [var-name-mixedcase](./rules/naming/var-name-mixedcase.md) | Variable name must be in mixedCase. (Does not check IMMUTABLES, use immutable-vars-naming) | $~~~~~~~~$✔️ | |
| [func-order](./rules/order/func-order.md) | Function order is incorrect. | | $~~~~~~~$✔️ |
| [imports-on-top](./rules/order/imports-on-top.md) | Import statements must be on top. | $~~~~~~~~$✔️ | |
| [ordering](./rules/order/ordering.md) | Check order of elements in file and inside each contract, according to the style guide. | | |
| [visibility-modifier-order](./rules/order/visibility-modifier-order.md) | Visibility modifier must be first in list of modifiers. | $~~~~~~~~$✔️ | |

## Security Rules

| Rule Id | Error | Recommended | Deprecated |
Expand Down
50 changes: 50 additions & 0 deletions docs/rules/naming/interface-starts-with-i.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
warning: "This is a dynamically generated file. Do not edit manually."
layout: "default"
title: "interface-starts-with-i | Solhint"
---

# interface-starts-with-i
![Category Badge](https://img.shields.io/badge/-Style%20Guide%20Rules-informational)
![Default Severity Badge warning](https://img.shields.io/badge/Default%20Severity-warning-undefined)

## Description
Solidity Interfaces names should start with an `I`

## Options
This rule accepts a string option of rule severity. Must be one of "error", "warn", "off". Default to warning.

### Example Config
```json
{
"rules": {
"interface-starts-with-i": "warning"
}
}
```


## Examples
### 👍 Examples of **correct** code for this rule

#### Interface name starts with I

```solidity
interface IFoo { function foo () external; }
```

### 👎 Examples of **incorrect** code for this rule

#### Interface name doesnt start with I

```solidity
interface Foo { function foo () external; }
```

## Version
This rule is introduced in the latest version.

## Resources
- [Rule source](https://github.com/protofire/solhint/tree/master/lib/rules/best-practises/interface-starts-with-i.js)
- [Document source](https://github.com/protofire/solhint/tree/master/docs/rules/best-practises/interface-starts-with-i.md)
- [Test cases](https://github.com/protofire/solhint/tree/master/test/rules/best-practises/interface-starts-with-i.js)
2 changes: 2 additions & 0 deletions lib/rules/best-practises/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const NoGlobalImportsChecker = require('./no-global-import')
const NoUnusedImportsChecker = require('./no-unused-import')
const ExplicitTypesChecker = require('./explicit-types')
const OneContractPerFileChecker = require('./one-contract-per-file')
const InterfaceStartsWithIChecker = require('./interface-starts-with-i')

module.exports = function checkers(reporter, config, inputSrc, tokens) {
return [
Expand All @@ -27,5 +28,6 @@ module.exports = function checkers(reporter, config, inputSrc, tokens) {
new NoUnusedImportsChecker(reporter, tokens),
new ExplicitTypesChecker(reporter, config),
new OneContractPerFileChecker(reporter),
new InterfaceStartsWithIChecker(reporter),
]
}
45 changes: 45 additions & 0 deletions lib/rules/best-practises/interface-starts-with-i.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const BaseChecker = require('../base-checker')

const ruleId = 'interface-starts-with-i'
const meta = {
type: 'naming',
docs: {
description: 'Solidity Interfaces names should start with an `I`',
category: 'Style Guide Rules',
examples: {
good: [
{
description: 'Interface name starts with I',
code: `interface IFoo { function foo () external; }`,
},
],
bad: [
{
description: 'Interface name doesnt start with I',
code: `interface Foo { function foo () external; }`,
},
],
},
},
isDefault: false,
recommended: false,
defaultSetup: 'warning',
schema: [],
}

class InterfaceStartsWithIChecker extends BaseChecker {
constructor(reporter) {
super(reporter, ruleId, meta)
}

ContractDefinition(node) {
if (node.kind !== 'interface') return
const interfaceName = node.name

if (!interfaceName.startsWith('I')) {
this.error(node, `Interface name '${interfaceName}' must start with "I"`)
}
}
}

module.exports = InterfaceStartsWithIChecker
23 changes: 23 additions & 0 deletions test/rules/best-practises/interface-starts-with-i.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const assert = require('assert')
const { processStr } = require('../../../lib/index')

const config = {
rules: { 'interface-starts-with-i': 'error' },
}

describe('Linter - interface-starts-with-i', () => {
it('should raise error for interface not starting with I', () => {
const code = 'interface Foo {}'
const report = processStr(code, config)

assert.equal(report.errorCount, 1)
assert.ok(report.messages[0].message === `Interface name 'Foo' must start with "I"`)
})

it('should not raise error for interface starting with I', () => {
const code = 'interface IFoo {}'

const report = processStr(code, config)
assert.equal(report.errorCount, 0)
})
})

0 comments on commit 10aa9f8

Please sign in to comment.