Repository: protofire/solhint
Pull request #449 (2023-07-11 15:39:30)

I051 list current rules being used by .solhint.json
This PR adds a new command to solhint command line
Typing `solhint list-rules` the program will display all covered rules of current .solhint.json

This will allow users to see what rules are actually being evaluated

Issue:
https://github.com/protofire/solhint/issues/51



Patch:
diff --git a/README.md b/README.md
index 507c31e..6d8e70e 100644
--- a/README.md
+++ b/README.md
@@ -67,6 +67,7 @@ Options:
 Commands:
 
   stdin [options]                         linting of source code data provided to STDIN
+  list-rules                              display covered rules of current .solhint.json
 ```
 ### Note
 The `--fix`  option currently works only on "avoid-throw" and "avoid-sha3" rules
diff --git a/lib/rules/best-practises/reason-string.js b/lib/rules/best-practises/reason-string.js
index f535b90..33b44a2 100644
--- a/lib/rules/best-practises/reason-string.js
+++ b/lib/rules/best-practises/reason-string.js
@@ -82,7 +82,12 @@ class ReasonStringChecker extends BaseChecker {
       // If has reason message and is too long, throw an error
       const reason = _.last(functionParameters).value
       if (reason.length > this.maxCharactersLong) {
-        this._errorMessageIsTooLong(node, functionName)
+        const infoMessage = reason.length
+          .toString()
+          .concat(' counted / ')
+          .concat(this.maxCharactersLong.toString())
+          .concat(' allowed')
+        this._errorMessageIsTooLong(node, functionName, infoMessage)
       }
     }
   }
@@ -103,8 +108,8 @@ class ReasonStringChecker extends BaseChecker {
     this.error(node, `Provide an error message for ${key}`)
   }
 
-  _errorMessageIsTooLong(node, key) {
-    this.error(node, `Error message for ${key} is too long`)
+  _errorMessageIsTooLong(node, key, infoMessage) {
+    this.error(node, `Error message for ${key} is too long: ${infoMessage}`)
   }
 }
 
diff --git a/solhint.js b/solhint.js
index 225aa94..30c150e 100644
--- a/solhint.js
+++ b/solhint.js
@@ -40,6 +40,11 @@ function init() {
     .description('create configuration file for solhint')
     .action(writeSampleConfigFile)
 
+  program
+    .command('list-rules', null, { noHelp: false })
+    .description('display covered rules of current .solhint.json')
+    .action(listRules)
+
   if (process.argv.length <= 2) {
     program.help()
   }
@@ -63,6 +68,7 @@ function execMainAction() {
 
   const reportLists = program.args.filter(_.isString).map(processPath)
   const reports = _.flatten(reportLists)
+
   const warningsCount = reports.reduce((acc, i) => acc + i.warningCount, 0)
   const warningsNumberExceeded =
     program.opts().maxWarnings >= 0 && warningsCount > program.opts().maxWarnings
@@ -207,6 +213,35 @@ function getFormatter(formatter) {
   }
 }
 
+function listRules() {
+  const configPath = '.solhint.json'
+  if (!fs.existsSync(configPath)) {
+    console.log('Error!! Configuration does not exists')
+    process.exit(0)
+  } else {
+    const config = readConfig()
+    console.log('\nConfiguration File: \n', config)
+
+    const reportLists = linter.processPath(configPath, readConfig())
+    const rulesObject = reportLists[0].config
+
+    console.log('\nRules: \n')
+    const orderedRules = Object.keys(rulesObject)
+      .sort()
+      .reduce((obj, key) => {
+        obj[key] = rulesObject[key]
+        return obj
+      }, {})
+
+    // eslint-disable-next-line func-names
+    Object.keys(orderedRules).forEach(function (key) {
+      console.log('- ', key, ': ', orderedRules[key])
+    })
+  }
+
+  process.exit(0)
+}
+
 function exitWithCode(reports) {
   const errorsCount = reports.reduce((acc, i) => acc + i.errorCount, 0)
 


Test patch:
diff --git a/test/rules/best-practises/reason-string.js b/test/rules/best-practises/reason-string.js
index c7f0cfd..30546d7 100644
--- a/test/rules/best-practises/reason-string.js
+++ b/test/rules/best-practises/reason-string.js
@@ -101,4 +101,25 @@ describe('Linter - reason-string', () => {
     assertNoWarnings(report)
     assertNoErrors(report)
   })
+
+  it('should raise reason string maxLength error with added data', () => {
+    const qtyChars = 'Roles: account already has role'.length
+    const maxLength = 5
+
+    const code = funcWith(`require(!has(role, account), "Roles: account already has role");
+        role.bearer[account] = true;role.bearer[account] = true;
+    `)
+
+    const report = linter.processStr(code, {
+      rules: { 'reason-string': ['warn', { maxLength: 5 }] },
+    })
+
+    assert.ok(report.warningCount > 0)
+    assertWarnsCount(report, 1)
+
+    assert.equal(
+      report.reports[0].message,
+      `Error message for require is too long: ${qtyChars} counted / ${maxLength} allowed`
+    )
+  })
 })