Repository: protofire/solhint
Pull request #458 (2023-07-27 15:23:09)

I243 [new rule] immutable as constants
- Added new rule: immutable as constants
Which has a configuration option to treat immutable variables as constants regarding notation (capital SNAKE_CASE) or as regular variables (mixedCase)

- Modified rule: var-name-mixedcase to disregard notation on immutable variables
- Modified rule: const-name-snakecase to disregard notation on immutable variables
- Several smaller fixes (notation and linter rules)


Patch:
diff --git a/.eslintrc.js b/.eslintrc.js
index 9bf4200..02e2d70 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -18,6 +18,7 @@ module.exports = {
     'global-require': 'off',
     'no-bitwise': 'off',
     'no-console': 'off',
+    'func-names': 'off',
     'no-continue': 'off',
     'no-else-return': 'off',
     'no-param-reassign': 'off',
diff --git a/.gitignore b/.gitignore
index 3614b26..77dd2e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ convertLib.sol
 antlr4.jar
 /docs/.sass-cache/
 _temp/
+.solhint.json
diff --git a/docs/rules.md b/docs/rules.md
index 10684fb..9765afd 100644
--- a/docs/rules.md
+++ b/docs/rules.md
@@ -6,20 +6,20 @@ title:       "Rule Index of Solhint"
 
 ## Best Practise Rules
 
-| Rule Id                                                            | Error                                                                                                                 | Recommended  | Deprecated |
-| ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | ------------ | ---------- |
-| [code-complexity](./rules/best-practises/code-complexity.md)       | Function has cyclomatic complexity "current" but allowed no more than maxcompl.                                       |              |            |
-| [function-max-lines](./rules/best-practises/function-max-lines.md) | Function body contains "count" lines but allowed no more than maxlines.                                               |              |            |
-| [max-line-length](./rules/best-practises/max-line-length.md)       | Line length must be no more than maxlen.                                                                              |              |            |
-| [max-states-count](./rules/best-practises/max-states-count.md)     | Contract has "some count" states declarations but allowed no more than maxstates.                                     | $~~~~~~~~$✔️ |            |
-| [no-console](./rules/best-practises/no-console.md)                 | No console.log/logInt/logBytesX/logString/etc & No hardhat and forge-std console.sol import statements                | $~~~~~~~~$✔️ |            |
-| [no-empty-blocks](./rules/best-practises/no-empty-blocks.md)       | Code contains empty block.                                                                                            | $~~~~~~~~$✔️ |            |
-| [no-global-import](./rules/best-practises/no-global-import.md)     | Import statement includes an entire file instead of selected symbols                                                  | $~~~~~~~~$✔️ |            |
-| [no-unused-import](./rules/best-practises/no-unused-import.md)     | Imported name is not used                                                                                             | $~~~~~~~~$✔️ |            |
-| [no-unused-vars](./rules/best-practises/no-unused-vars.md)         | Variable "name" is unused.                                                                                            | $~~~~~~~~$✔️ |            |
-| [payable-fallback](./rules/best-practises/payable-fallback.md)     | When fallback is not payable you will not be able to receive ethers.                                                  | $~~~~~~~~$✔️ |            |
-| [reason-string](./rules/best-practises/reason-string.md)           | Require or revert statement must have a reason string and check that each reason string is at most N characters long. | $~~~~~~~~$✔️ |            |
-| [constructor-syntax](./rules/best-practises/constructor-syntax.md) | Constructors should use the new constructor keyword.                                                                  |              |            |
+| Rule Id                                                            | Error                                                                                                                 | Recommended |
+| ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | ----------- |
+| [code-complexity](./rules/best-practises/code-complexity.md)       | Function has cyclomatic complexity "current" but allowed no more than maxcompl.                                       |             |
+| [function-max-lines](./rules/best-practises/function-max-lines.md) | Function body contains "count" lines but allowed no more than maxlines.                                               |             |
+| [max-line-length](./rules/best-practises/max-line-length.md)       | Line length must be no more than maxlen.                                                                              |             |
+| [max-states-count](./rules/best-practises/max-states-count.md)     | Contract has "some count" states declarations but allowed no more than maxstates.                                     | ✔️          |
+| [no-console](./rules/best-practises/no-console.md)                 | No console.log/logInt/logBytesX/logString/etc & No hardhat and forge-std console.sol import statements.               | ✔️          |
+| [no-empty-blocks](./rules/best-practises/no-empty-blocks.md)       | Code contains empty block.                                                                                            | ✔️          |
+| [no-global-import](./rules/best-practises/no-global-import.md)     | Import statement includes an entire file instead of selected symbols.                                                 | ✔️          |
+| [no-unused-import](./rules/best-practises/no-unused-import.md)     | Imported name is not used.                                                                                            | ✔️          |
+| [no-unused-vars](./rules/best-practises/no-unused-vars.md)         | Variable "name" is unused.                                                                                            | ✔️          |
+| [payable-fallback](./rules/best-practises/payable-fallback.md)     | When fallback is not payable you will not be able to receive ethers.                                                  | ✔️          |
+| [reason-string](./rules/best-practises/reason-string.md)           | Require or revert statement must have a reason string and check that each reason string is at most N characters long. | ✔️          |
+| [constructor-syntax](./rules/best-practises/constructor-syntax.md) | Constructors should use the new constructor keyword.                                                                  |             |
         
 
 ## Miscellaneous
@@ -32,22 +32,23 @@ title:       "Rule Index of Solhint"
 
 ## 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.                                       | $~~~~~~~~$✔️ |             |
-| [contract-name-camelcase](./rules/naming/contract-name-camelcase.md)                 | Contract name must be in CamelCase.                                                    | $~~~~~~~~$✔️ |             |
-| [event-name-camelcase](./rules/naming/event-name-camelcase.md)                       | Event name must be in CamelCase.                                                       | $~~~~~~~~$✔️ |             |
-| [func-name-mixedcase](./rules/naming/func-name-mixedcase.md)                         | Function name must be in mixedCase.                                                    | $~~~~~~~~$✔️ |             |
-| [func-param-name-mixedcase](./rules/naming/func-param-name-mixedcase.md)             | Function param name must be in mixedCase                                               |              |             |
-| [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) | Private and internal names must start with a single underscore.                        |              |             |
-| [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.                                                    | $~~~~~~~~$✔️ |             |
-| [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.                                | $~~~~~~~~$✔️ |             |
+| Rule Id                                                                              | Error                                                                                                   | Recommended |
+| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- | ----------- |
+| [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 name must be in CamelCase.                                                                     | ✔️          |
+| [event-name-camelcase](./rules/naming/event-name-camelcase.md)                       | Event name must be in CamelCase.                                                                        | ✔️          |
+| [func-name-mixedcase](./rules/naming/func-name-mixedcase.md)                         | Function name must be in mixedCase.                                                                     | ✔️          |
+| [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) | Private and internal names must start with a single underscore.                                         |             |
+| [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
diff --git a/docs/rules/best-practises/no-console.md b/docs/rules/best-practises/no-console.md
index 6fc4cb3..da6676e 100644
--- a/docs/rules/best-practises/no-console.md
+++ b/docs/rules/best-practises/no-console.md
@@ -14,7 +14,7 @@ title:       "no-console | Solhint"
 
 
 ## Description
-No console.log/logInt/logBytesX/logString/etc & No hardhat and forge-std console.sol import statements
+No console.log/logInt/logBytesX/logString/etc & No hardhat and forge-std console.sol import statements.
 
 ## Options
 This rule accepts a string option of rule severity. Must be one of "error", "warn", "off". Default to error.
diff --git a/docs/rules/best-practises/no-global-import.md b/docs/rules/best-practises/no-global-import.md
index dd16447..1d95ccd 100644
--- a/docs/rules/best-practises/no-global-import.md
+++ b/docs/rules/best-practises/no-global-import.md
@@ -12,7 +12,7 @@ title:       "no-global-import | Solhint"
 
 
 ## Description
-Import statement includes an entire file instead of selected symbols
+Import statement includes an entire file instead of selected symbols.
 
 ## Options
 This rule accepts a string option of rule severity. Must be one of "error", "warn", "off". Default to warn.
diff --git a/docs/rules/best-practises/no-unused-import.md b/docs/rules/best-practises/no-unused-import.md
index e03199a..5643b9f 100644
--- a/docs/rules/best-practises/no-unused-import.md
+++ b/docs/rules/best-practises/no-unused-import.md
@@ -12,7 +12,7 @@ title:       "no-unused-import | Solhint"
 
 
 ## Description
-Imported name is not used
+Imported name is not used.
 
 ## Options
 This rule accepts a string option of rule severity. Must be one of "error", "warn", "off". Default to warn.
diff --git a/docs/rules/naming/const-name-snakecase.md b/docs/rules/naming/const-name-snakecase.md
index 711bc56..fc5cb3a 100644
--- a/docs/rules/naming/const-name-snakecase.md
+++ b/docs/rules/naming/const-name-snakecase.md
@@ -12,7 +12,7 @@ title:       "const-name-snakecase | Solhint"
 
 
 ## Description
-Constant name must be in capitalized SNAKE_CASE.
+Constant name must be in capitalized SNAKE_CASE. (Does not check IMMUTABLES, use immutable-vars-naming)
 
 ## Options
 This rule accepts a string option of rule severity. Must be one of "error", "warn", "off". Default to warn.
diff --git a/docs/rules/naming/func-param-name-mixedcase.md b/docs/rules/naming/func-param-name-mixedcase.md
index b1f9397..3ad1965 100644
--- a/docs/rules/naming/func-param-name-mixedcase.md
+++ b/docs/rules/naming/func-param-name-mixedcase.md
@@ -9,7 +9,7 @@ title:       "func-param-name-mixedcase | Solhint"
 ![Default Severity Badge warn](https://img.shields.io/badge/Default%20Severity-warn-yellow)
 
 ## Description
-Function param name must be in mixedCase
+Function param name must be in mixedCase.
 
 ## Options
 This rule accepts a string option of rule severity. Must be one of "error", "warn", "off". Default to warn.
diff --git a/docs/rules/naming/immutable-vars-naming.md b/docs/rules/naming/immutable-vars-naming.md
new file mode 100644
index 0000000..8705d7e
--- /dev/null
+++ b/docs/rules/naming/immutable-vars-naming.md
@@ -0,0 +1,45 @@
+---
+warning:     "This is a dynamically generated file. Do not edit manually."
+layout:      "default"
+title:       "immutable-vars-naming | Solhint"
+---
+
+# immutable-vars-naming
+![Recommended Badge](https://img.shields.io/badge/-Recommended-brightgreen)
+![Category Badge](https://img.shields.io/badge/-Style%20Guide%20Rules-informational)
+![Default Severity Badge warn](https://img.shields.io/badge/Default%20Severity-warn-yellow)
+> The {"extends": "solhint:recommended"} property in a configuration file enables this rule.
+
+
+## Description
+Check Immutable variables. Capitalized SNAKE_CASE or mixedCase depending on configuration.
+
+## Options
+This rule accepts an array of options:
+
+| Index | Description                                                                                                                              | Default Value                  |
+| ----- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
+| 0     | Rule severity. Must be one of "error", "warn", "off".                                                                                    | warn                           |
+| 1     | A JSON object with a single property "immutablesAsConstants" as boolean specifying if immutable variables should be treated as constants | {"immutablesAsConstants":true} |
+
+
+### Example Config
+```json
+{
+  "rules": {
+    "immutable-vars-naming": ["warn",{"immutablesAsConstants":true}]
+  }
+}
+```
+
+
+## Examples
+This rule does not have examples.
+
+## Version
+This rule is introduced in the latest version.
+
+## Resources
+- [Rule source](https://github.com/protofire/solhint/tree/master/lib/rules/naming/immutable-vars-naming.js)
+- [Document source](https://github.com/protofire/solhint/tree/master/docs/rules/naming/immutable-vars-naming.md)
+- [Test cases](https://github.com/protofire/solhint/tree/master/test/rules/naming/immutable-vars-naming.js)
diff --git a/docs/rules/naming/named-parameters-mapping.md b/docs/rules/naming/named-parameters-mapping.md
index f23c7a8..6ae1557 100644
--- a/docs/rules/naming/named-parameters-mapping.md
+++ b/docs/rules/naming/named-parameters-mapping.md
@@ -9,7 +9,7 @@ title:       "named-parameters-mapping | Solhint"
 ![Default Severity Badge off](https://img.shields.io/badge/Default%20Severity-off-undefined)
 
 ## Description
-Solidity v0.8.18 introduced named parameters on the mappings definition
+Solidity v0.8.18 introduced named parameters on the mappings definition.
 
 ## Options
 This rule accepts a string option of rule severity. Must be one of "error", "warn", "off". Default to off.
diff --git a/docs/rules/naming/var-name-mixedcase.md b/docs/rules/naming/var-name-mixedcase.md
index 824735f..913a62c 100644
--- a/docs/rules/naming/var-name-mixedcase.md
+++ b/docs/rules/naming/var-name-mixedcase.md
@@ -12,7 +12,7 @@ title:       "var-name-mixedcase | Solhint"
 
 
 ## Description
-Variable name must be in mixedCase.
+Variable name must be in mixedCase. (Does not check IMMUTABLES, use immutable-vars-naming)
 
 ## Options
 This rule accepts a string option of rule severity. Must be one of "error", "warn", "off". Default to warn.
diff --git a/docs/rules/order/ordering.md b/docs/rules/order/ordering.md
index 421c836..5e0d009 100644
--- a/docs/rules/order/ordering.md
+++ b/docs/rules/order/ordering.md
@@ -9,7 +9,7 @@ title:       "ordering | Solhint"
 ![Default Severity Badge warn](https://img.shields.io/badge/Default%20Severity-warn-yellow)
 
 ## Description
-Check order of elements in file and inside each contract, according to the style guide
+Check order of elements in file and inside each contract, according to the style guide.
 
 ## Options
 This rule accepts a string option of rule severity. Must be one of "error", "warn", "off". Default to warn.
diff --git a/lib/rules/best-practises/no-console.js b/lib/rules/best-practises/no-console.js
index 485c020..e6b26af 100644
--- a/lib/rules/best-practises/no-console.js
+++ b/lib/rules/best-practises/no-console.js
@@ -5,7 +5,7 @@ const meta = {
   type: 'best-practises',
   docs: {
     description:
-      'No console.log/logInt/logBytesX/logString/etc & No hardhat and forge-std console.sol import statements',
+      'No console.log/logInt/logBytesX/logString/etc & No hardhat and forge-std console.sol import statements.',
     category: 'Best Practise Rules',
     examples: {
       bad: [
diff --git a/lib/rules/best-practises/no-global-import.js b/lib/rules/best-practises/no-global-import.js
index 2f3e27b..a4e337a 100644
--- a/lib/rules/best-practises/no-global-import.js
+++ b/lib/rules/best-practises/no-global-import.js
@@ -5,7 +5,7 @@ const meta = {
   type: 'best-practises',
 
   docs: {
-    description: 'Import statement includes an entire file instead of selected symbols',
+    description: 'Import statement includes an entire file instead of selected symbols.',
     category: 'Best Practise Rules',
     examples: {
       bad: [
diff --git a/lib/rules/best-practises/no-unused-import.js b/lib/rules/best-practises/no-unused-import.js
index 5e80100..78ba6f7 100644
--- a/lib/rules/best-practises/no-unused-import.js
+++ b/lib/rules/best-practises/no-unused-import.js
@@ -6,7 +6,7 @@ const meta = {
   type: 'best-practises',
 
   docs: {
-    description: 'Imported name is not used',
+    description: 'Imported name is not used.',
     category: 'Best Practise Rules',
   },
 
diff --git a/lib/rules/naming/const-name-snakecase.js b/lib/rules/naming/const-name-snakecase.js
index dc10fde..9f7e961 100644
--- a/lib/rules/naming/const-name-snakecase.js
+++ b/lib/rules/naming/const-name-snakecase.js
@@ -6,7 +6,8 @@ const meta = {
   type: 'naming',
 
   docs: {
-    description: 'Constant name must be in capitalized SNAKE_CASE.',
+    description:
+      'Constant name must be in capitalized SNAKE_CASE. (Does not check IMMUTABLES, use immutable-vars-naming)',
     category: 'Style Guide Rules',
   },
 
diff --git a/lib/rules/naming/func-param-name-mixedcase.js b/lib/rules/naming/func-param-name-mixedcase.js
index 204c49b..56dae1f 100644
--- a/lib/rules/naming/func-param-name-mixedcase.js
+++ b/lib/rules/naming/func-param-name-mixedcase.js
@@ -6,7 +6,7 @@ const meta = {
   type: 'naming',
 
   docs: {
-    description: 'Function param name must be in mixedCase',
+    description: 'Function param name must be in mixedCase.',
     category: 'Style Guide Rules',
   },
 
diff --git a/lib/rules/naming/immutable-vars-naming.js b/lib/rules/naming/immutable-vars-naming.js
new file mode 100644
index 0000000..5a26d3b
--- /dev/null
+++ b/lib/rules/naming/immutable-vars-naming.js
@@ -0,0 +1,80 @@
+const BaseChecker = require('../base-checker')
+const naming = require('../../common/identifier-naming')
+const { severityDescription } = require('../../doc/utils')
+
+const DEFAULT_INMUTABLE_AS_CONSTANTS = true
+const DEFAULT_SEVERITY = 'warn'
+const DEFAULT_OPTION = { immutablesAsConstants: DEFAULT_INMUTABLE_AS_CONSTANTS }
+
+const ruleId = 'immutable-vars-naming'
+const meta = {
+  type: 'naming',
+
+  docs: {
+    description:
+      'Check Immutable variables. Capitalized SNAKE_CASE or mixedCase depending on configuration.',
+    category: 'Style Guide Rules',
+    options: [
+      {
+        description: severityDescription,
+        default: DEFAULT_SEVERITY,
+      },
+      {
+        description:
+          'A JSON object with a single property "immutablesAsConstants" as boolean specifying if immutable variables should be treated as constants',
+        default: JSON.stringify(DEFAULT_OPTION),
+      },
+    ],
+  },
+
+  isDefault: false,
+  recommended: true,
+  defaultSetup: [DEFAULT_SEVERITY, DEFAULT_OPTION],
+
+  schema: {
+    type: 'object',
+    properties: {
+      immutablesAsConstants: {
+        type: 'boolean',
+      },
+    },
+  },
+}
+
+class ImmutableVarsNamingChecker extends BaseChecker {
+  constructor(reporter, config) {
+    super(reporter, ruleId, meta)
+
+    this.treatImmutablesAsConstants =
+      config &&
+      config.getObjectPropertyBoolean(
+        ruleId,
+        'immutablesAsConstants',
+        DEFAULT_INMUTABLE_AS_CONSTANTS
+      )
+  }
+
+  VariableDeclaration(node) {
+    if (node.isImmutable) {
+      if (this.treatImmutablesAsConstants) {
+        this.validateImmutableAsConstantName(node)
+      } else {
+        this.validateImmutableAsRegularVariables(node)
+      }
+    }
+  }
+
+  validateImmutableAsConstantName(node) {
+    if (naming.isNotUpperSnakeCase(node.name)) {
+      this.error(node, 'Immutable variables name are set to be in capitalized SNAKE_CASE')
+    }
+  }
+
+  validateImmutableAsRegularVariables(node) {
+    if (naming.isNotMixedCase(node.name)) {
+      this.error(node, 'Immutable variables names are set to be in mixedCase')
+    }
+  }
+}
+
+module.exports = ImmutableVarsNamingChecker
diff --git a/lib/rules/naming/index.js b/lib/rules/naming/index.js
index ad0a9e5..60db92c 100644
--- a/lib/rules/naming/index.js
+++ b/lib/rules/naming/index.js
@@ -4,10 +4,11 @@ const EventNameCamelcaseChecker = require('./event-name-camelcase')
 const FuncNameMixedcaseChecker = require('./func-name-mixedcase')
 const FuncParamNameMixedcaseChecker = require('./func-param-name-mixedcase')
 const ModifierNameMixedcaseChecker = require('./modifier-name-mixedcase')
-const PrivateVarsLeadingUnderscore = require('./private-vars-leading-underscore')
+const PrivateVarsLeadingUnderscoreChecker = require('./private-vars-leading-underscore')
 const UseForbiddenNameChecker = require('./use-forbidden-name')
 const VarNameMixedcaseChecker = require('./var-name-mixedcase')
-const NamedParametersMapping = require('./named-parameters-mapping')
+const NamedParametersMappingChecker = require('./named-parameters-mapping')
+const ImmutableVarsNamingChecker = require('./immutable-vars-naming')
 
 module.exports = function checkers(reporter, config) {
   return [
@@ -17,9 +18,10 @@ module.exports = function checkers(reporter, config) {
     new FuncNameMixedcaseChecker(reporter),
     new FuncParamNameMixedcaseChecker(reporter),
     new ModifierNameMixedcaseChecker(reporter),
-    new PrivateVarsLeadingUnderscore(reporter, config),
+    new PrivateVarsLeadingUnderscoreChecker(reporter, config),
     new UseForbiddenNameChecker(reporter),
     new VarNameMixedcaseChecker(reporter),
-    new NamedParametersMapping(reporter),
+    new NamedParametersMappingChecker(reporter),
+    new ImmutableVarsNamingChecker(reporter, config),
   ]
 }
diff --git a/lib/rules/naming/named-parameters-mapping.js b/lib/rules/naming/named-parameters-mapping.js
index 099e71c..4452d0d 100644
--- a/lib/rules/naming/named-parameters-mapping.js
+++ b/lib/rules/naming/named-parameters-mapping.js
@@ -4,7 +4,7 @@ const ruleId = 'named-parameters-mapping'
 const meta = {
   type: 'naming',
   docs: {
-    description: `Solidity v0.8.18 introduced named parameters on the mappings definition`,
+    description: `Solidity v0.8.18 introduced named parameters on the mappings definition.`,
     category: 'Style Guide Rules',
     examples: {
       good: [
@@ -60,7 +60,7 @@ const meta = {
   schema: null,
 }
 
-class NamedParametersMapping extends BaseChecker {
+class NamedParametersMappingChecker extends BaseChecker {
   constructor(reporter) {
     super(reporter, ruleId, meta)
   }
@@ -109,4 +109,4 @@ class NamedParametersMapping extends BaseChecker {
   }
 }
 
-module.exports = NamedParametersMapping
+module.exports = NamedParametersMappingChecker
diff --git a/lib/rules/naming/var-name-mixedcase.js b/lib/rules/naming/var-name-mixedcase.js
index a7268da..3e9581c 100644
--- a/lib/rules/naming/var-name-mixedcase.js
+++ b/lib/rules/naming/var-name-mixedcase.js
@@ -6,7 +6,7 @@ const meta = {
   type: 'naming',
 
   docs: {
-    description: `Variable name must be in mixedCase.`,
+    description: `Variable name must be in mixedCase. (Does not check IMMUTABLES, use immutable-vars-naming)`,
     category: 'Style Guide Rules',
   },
 
@@ -23,7 +23,7 @@ class VarNameMixedcaseChecker extends BaseChecker {
   }
 
   VariableDeclaration(node) {
-    if (!node.isDeclaredConst) {
+    if (!node.isDeclaredConst && !node.isImmutable) {
       this.validateVariablesName(node)
     }
   }
diff --git a/lib/rules/order/ordering.js b/lib/rules/order/ordering.js
index 19c731f..494f3ad 100644
--- a/lib/rules/order/ordering.js
+++ b/lib/rules/order/ordering.js
@@ -6,7 +6,7 @@ const meta = {
   type: 'order',
 
   docs: {
-    description: `Check order of elements in file and inside each contract, according to the style guide`,
+    description: `Check order of elements in file and inside each contract, according to the style guide.`,
     category: 'Style Guide Rules',
     examples: {
       good: require('../../../test/fixtures/order/ordering-correct'),


Test patch:
diff --git a/test/rules/naming/const-name-snakecase.js b/test/rules/naming/const-name-snakecase.js
index 95289ab..125c530 100644
--- a/test/rules/naming/const-name-snakecase.js
+++ b/test/rules/naming/const-name-snakecase.js
@@ -54,4 +54,24 @@ describe('Linter - const-name-snakecase', () => {
     assert.equal(report.errorCount, 1)
     assert.ok(report.messages[0].message.includes('SNAKE_CASE'))
   })
+
+  it('should not raise const name error for immutable variables in SNAKE_CASE', () => {
+    const code = contractWith('uint32 private immutable SNAKE_CASE;')
+
+    const report = linter.processStr(code, {
+      rules: { 'const-name-snakecase': 'error' },
+    })
+
+    assert.equal(report.errorCount, 0)
+  })
+
+  it('should not raise const name error for immutable variables in mixedCase', () => {
+    const code = contractWith('uint32 private immutable SNAKE_CASE;')
+
+    const report = linter.processStr(code, {
+      rules: { 'const-name-snakecase': 'error' },
+    })
+
+    assert.equal(report.errorCount, 0)
+  })
 })
diff --git a/test/rules/naming/immutable-vars-naming.js b/test/rules/naming/immutable-vars-naming.js
new file mode 100644
index 0000000..4b9cb7d
--- /dev/null
+++ b/test/rules/naming/immutable-vars-naming.js
@@ -0,0 +1,117 @@
+const assert = require('assert')
+const linter = require('../../../lib/index')
+const contractWith = require('../../common/contract-builder').contractWith
+
+describe('immutable-vars-naming', () => {
+  it('should not raise error for non immutable variables if rule is off', () => {
+    const code = contractWith('uint32 private immutable D;')
+
+    const report = linter.processStr(code, {
+      rules: {
+        'immutable-vars-naming': 'off',
+        'var-name-mixedcase': 'error',
+        'const-name-snakecase': 'error',
+      },
+    })
+
+    assert.equal(report.errorCount, 0)
+  })
+
+  it('should raise error when immutablesAsConstants = false and variable is in snake case', () => {
+    const code = contractWith('uint32 private immutable SNAKE_CASE;')
+
+    const report = linter.processStr(code, {
+      rules: { 'immutable-vars-naming': ['error', { immutablesAsConstants: false }] },
+    })
+
+    assert.equal(report.errorCount, 1)
+    assert.ok(
+      report.messages[0].message.includes('Immutable variables names are set to be in mixedCase')
+    )
+  })
+
+  it('should NOT raise error when immutablesAsConstants = false and variable is in snake case', () => {
+    const code = contractWith('uint32 private immutable SNAKE_CASE;')
+
+    const report = linter.processStr(code, {
+      rules: { 'immutable-vars-naming': ['error', { immutablesAsConstants: true }] },
+    })
+
+    assert.equal(report.errorCount, 0)
+  })
+
+  it('should raise error when immutablesAsConstants = true and variable is in mixedCase', () => {
+    const code = contractWith('uint32 private immutable mixedCase;')
+
+    const report = linter.processStr(code, {
+      rules: { 'immutable-vars-naming': ['error', { immutablesAsConstants: true }] },
+    })
+
+    assert.equal(report.errorCount, 1)
+    assert.ok(
+      report.messages[0].message.includes(
+        'Immutable variables name are set to be in capitalized SNAKE_CASE'
+      )
+    )
+  })
+
+  it('should NOT raise error when immutablesAsConstants = false and variable is in mixedCase', () => {
+    const code = contractWith('uint32 private immutable mixedCase;')
+
+    const report = linter.processStr(code, {
+      rules: { 'immutable-vars-naming': ['error', { immutablesAsConstants: false }] },
+    })
+
+    assert.equal(report.errorCount, 0)
+  })
+
+  describe('immutable-vars-naming ==> warnings (same as above)', () => {
+    it('should raise warning when immutablesAsConstants = false and variable is in snake case', () => {
+      const code = contractWith('uint32 private immutable SNAKE_CASE;')
+
+      const report = linter.processStr(code, {
+        rules: { 'immutable-vars-naming': ['warn', { immutablesAsConstants: false }] },
+      })
+
+      assert.equal(report.warningCount, 1)
+      assert.ok(
+        report.messages[0].message.includes('Immutable variables names are set to be in mixedCase')
+      )
+    })
+
+    it('should NOT raise warning when immutablesAsConstants = false and variable is in snake case', () => {
+      const code = contractWith('uint32 private immutable SNAKE_CASE;')
+
+      const report = linter.processStr(code, {
+        rules: { 'immutable-vars-naming': ['warn', { immutablesAsConstants: true }] },
+      })
+
+      assert.equal(report.warningCount, 0)
+    })
+
+    it('should raise warning when immutablesAsConstants = true and variable is in mixedCase', () => {
+      const code = contractWith('uint32 private immutable mixedCase;')
+
+      const report = linter.processStr(code, {
+        rules: { 'immutable-vars-naming': ['warn', { immutablesAsConstants: true }] },
+      })
+
+      assert.equal(report.warningCount, 1)
+      assert.ok(
+        report.messages[0].message.includes(
+          'Immutable variables name are set to be in capitalized SNAKE_CASE'
+        )
+      )
+    })
+
+    it('should NOT raise warning when immutablesAsConstants = false and variable is in mixedCase', () => {
+      const code = contractWith('uint32 private immutable mixedCase;')
+
+      const report = linter.processStr(code, {
+        rules: { 'immutable-vars-naming': ['warn', { immutablesAsConstants: false }] },
+      })
+
+      assert.equal(report.warningCount, 0)
+    })
+  })
+})
diff --git a/test/rules/naming/var-name-mixedcase.js b/test/rules/naming/var-name-mixedcase.js
index 13fa86e..635a792 100644
--- a/test/rules/naming/var-name-mixedcase.js
+++ b/test/rules/naming/var-name-mixedcase.js
@@ -46,4 +46,24 @@ describe('Linter - var-name-mixedcase', () => {
 
     assert.equal(report.errorCount, 0)
   })
+
+  it('should not raise const name error for immutable variables in SNAKE_CASE', () => {
+    const code = contractWith('uint32 private immutable SNAKE_CASE;')
+
+    const report = linter.processStr(code, {
+      rules: { 'no-unused-vars': 'error', 'var-name-mixedcase': 'error' },
+    })
+
+    assert.equal(report.errorCount, 0)
+  })
+
+  it('should not raise const name error for immutable variables in mixedCase', () => {
+    const code = contractWith('uint32 private immutable SNAKE_CASE;')
+
+    const report = linter.processStr(code, {
+      rules: { 'no-unused-vars': 'error', 'var-name-mixedcase': 'error' },
+    })
+
+    assert.equal(report.errorCount, 0)
+  })
 })