Repository: protofire/solhint
Pull request #391 (2023-01-26 14:20:48)

fix: no-console rule update
There was an error in the no-console rule preventing to invoke any method in a variable including the 'console' string.
This update fix that. Tests included.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 85a318f..beb7849 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,17 +1,3 @@
-## [3.3.9] - TBD
-
-### Updated
-- Update solhint dependencies to support newer versions [#380](https://github.com/protofire/solhint/pull/380)
-- Linter fixed to get clearer source code [#381](https://github.com/protofire/solhint/pull/381)
-- Updated E2E, added formatters into repo, updated CI [#385](https://github.com/protofire/solhint/pull/385)
-
-### Added
-- Lint rule for banning "console.sol" and "import hardhat or foundry console.sol" [#372](https://github.com/protofire/solhint/pull/372)
-
-### Fixed
-- Directories with .sol in the name path treated as files [#352](https://github.com/protofire/solhint/pull/388)
-
-<br><br>
 ## [3.3.8] - 2023-01-17
 ### Fixed Docs and Typos
 - [#292](https://github.com/protofire/solhint/pull/292)
@@ -19,6 +5,8 @@
 - [#355](https://github.com/protofire/solhint/pull/355)
 - [#285](https://github.com/protofire/solhint/pull/285)
   
+### Added
+- Lint rule for banning "console.sol" and "import hardhat/console.sol" [#372](https://github.com/protofire/solhint/pull/372)
 
 ### Updated
 - Solidity Parser to 0.14.5 [#378](https://github.com/protofire/solhint/pull/378)
diff --git a/docs/rules.md b/docs/rules.md
index b656971..45f369a 100644
--- a/docs/rules.md
+++ b/docs/rules.md
@@ -4,7 +4,7 @@ layout:      "default"
 title:       "Rule Index of Solhint"
 ---
 
-## Best Practise Rules
+## Best Practice Rules
 
 | Rule Id                                                            | Error                                                                                                                 | Recommended |
 | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | ----------- |
@@ -12,7 +12,6 @@ title:       "Rule Index of Solhint"
 | [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-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.                                                  | ✔️          |
@@ -35,7 +34,7 @@ title:       "Rule Index of Solhint"
 | [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-name-mixedcase](./rules/naming/func-name-mixedcase.md)                         | Function name must be in camelCase.                                                    | ✔️          |
 | [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.                                                    |             |
 | [private-vars-leading-underscore](./rules/naming/private-vars-leading-underscore.md) | Private and internal names must start with a single underscore.                        |             |
@@ -65,7 +64,7 @@ title:       "Rule Index of Solhint"
 | [no-complex-fallback](./rules/security/no-complex-fallback.md)         | Fallback function must be simple.                                        | ✔️          |
 | [no-inline-assembly](./rules/security/no-inline-assembly.md)           | Avoid to use inline assembly. It is acceptable only in rare cases.       | ✔️          |
 | [not-rely-on-block-hash](./rules/security/not-rely-on-block-hash.md)   | Do not rely on "block.blockhash". Miners can influence its value.        | ✔️          |
-| [not-rely-on-time](./rules/security/not-rely-on-time.md)               | Avoid making time-based decisions in your business logic.                | ✔️          |
+| [not-rely-on-time](./rules/security/not-rely-on-time.md)               | Avoid making time-based decisions in your business logic.               | ✔️          |
 | [reentrancy](./rules/security/reentrancy.md)                           | Possible reentrancy vulnerabilities. Avoid state changes after transfer. | ✔️          |
 | [state-visibility](./rules/security/state-visibility.md)               | Explicitly mark visibility of state.                                     | ✔️          |
         
diff --git a/docs/rules/best-practises/no-console.md b/docs/rules/best-practises/no-console.md
deleted file mode 100644
index 294429b..0000000
--- a/docs/rules/best-practises/no-console.md
+++ /dev/null
@@ -1,59 +0,0 @@
----
-warning:     "This is a dynamically generated file. Do not edit manually."
-layout:      "default"
-title:       "no-console | Solhint"
----
-
-# no-console
-![Recommended Badge](https://img.shields.io/badge/-Recommended-brightgreen)
-![Category Badge](https://img.shields.io/badge/-Best%20Practise%20Rules-informational)
-![Default Severity Badge error](https://img.shields.io/badge/Default%20Severity-error-red)
-> The {"extends": "solhint:default"} property in a configuration file enables this rule.
-
-> The {"extends": "solhint:recommended"} property in a configuration file enables this rule.
-
-
-## Description
-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.
-
-### Example Config
-```json
-{
-  "rules": {
-    "no-console": "error"
-  }
-}
-```
-
-
-## Examples
-### 👎 Examples of **incorrect** code for this rule
-
-#### No console.logX statements
-
-```solidity
-console.log('test')
-```
-
-#### No hardhat/console.sol import statements
-
-```solidity
-import "hardhat/console.sol"
-```
-
-#### No forge-std console.sol & console2.sol import statements
-
-```solidity
-import "forge-std/consoleN.sol"
-```
-
-## Version
-This rule is introduced in the latest version.
-
-## Resources
-- [Rule source](https://github.com/protofire/solhint/tree/master/lib/rules/best-practises/no-console.js)
-- [Document source](https://github.com/protofire/solhint/tree/master/docs/rules/best-practises/no-console.md)
-- [Test cases](https://github.com/protofire/solhint/tree/master/test/rules/best-practises/no-console.js)
diff --git a/docs/rules/miscellaneous/comprehensive-interface.md b/docs/rules/miscellaneous/comprehensive-interface.md
index 6ec24fc..5fc5e7f 100644
--- a/docs/rules/miscellaneous/comprehensive-interface.md
+++ b/docs/rules/miscellaneous/comprehensive-interface.md
@@ -9,7 +9,7 @@ title:       "comprehensive-interface | Solhint"
 ![Default Severity Badge warn](https://img.shields.io/badge/Default%20Severity-warn-yellow)
 
 ## Description
-Check that all public or external functions are override. This is iseful to make sure that the whole API is extracted in an interface.
+Check that all public or external functions are override. This is useful to make sure that the whole API is extracted in an interface.
 
 ## 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-name-mixedcase.md b/docs/rules/naming/func-name-mixedcase.md
index c51e216..d5ad8c8 100644
--- a/docs/rules/naming/func-name-mixedcase.md
+++ b/docs/rules/naming/func-name-mixedcase.md
@@ -12,7 +12,7 @@ title:       "func-name-mixedcase | Solhint"
 
 
 ## Description
-Function name must be in mixedCase.
+Function name must be in camelCase.
 
 ## 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..34a1432 100644
--- a/docs/rules/order/ordering.md
+++ b/docs/rules/order/ordering.md
@@ -27,220 +27,79 @@ This rule accepts a string option of rule severity. Must be one of "error", "war
 ## Examples
 ### 👍 Examples of **correct** code for this rule
 
-#### All units are in order - ^0.4.0
+#### All units are in order
 
 ```solidity
-
-pragma solidity ^0.4.0;
-
-import "./some/library.sol";
-import "./some/other-library.sol";
-
-enum MyEnum {
-  Foo,
-  Bar
-}
-
-struct MyStruct {
-  uint x;
-  uint y;
-}
-
-interface IBox {
-  function getValue() public;
-  function setValue(uint) public;
-}
-
-library MyLibrary {
-  function add(uint a, uint b, uint c) public returns (uint) {
-    return a + b + c;
-  }
-}
-
-contract MyContract {
-  struct InnerStruct {
-    bool flag;
-  }
-
-  enum InnerEnum {
-    A, B, C
-  }
-
-  uint public x;
-  uint public y;
-
-  event MyEvent(address a);
-
-  constructor () public {}
-
-  fallback () external {}
-
-  function myExternalFunction() external {}
-  function myExternalConstantFunction() external constant {}
-
-  function myPublicFunction() public {}
-  function myPublicConstantFunction() public constant {}
-
-  function myInternalFunction() internal {}
-  function myPrivateFunction() private {}
-}
-
-```
-
-#### All units are in order - ^0.5.0
-
-```solidity
-
-pragma solidity ^0.5.0;
-
-import "./some/library.sol";
-import "./some/other-library.sol";
-
-enum MyEnum {
-  Foo,
-  Bar
-}
-
-struct MyStruct {
-  uint x;
-  uint y;
-}
-
-interface IBox {
-  function getValue() public;
-  function setValue(uint) public;
-}
-
-library MyLibrary {
-  function add(uint a, uint b, uint c) public returns (uint) {
-    return a + b + c;
-  }
-}
-
-contract MyContract {
-  using MyLibrary for uint;
-
-  struct InnerStruct {
-    bool flag;
-  }
-
-  enum InnerEnum {
-    A, B, C
-  }
-
-  address payable owner;
-  uint public x;
-  uint public y;
-
-  event MyEvent(address a);
-
-  modifier onlyOwner {
-    require(
-      msg.sender == owner,
-      "Only owner can call this function."
-    );
-    _;
-  }
-
-  constructor () public {}
-
-  fallback () external {}
-
-  function myExternalFunction() external {}
-  function myExternalViewFunction() external view {}
-  function myExternalPureFunction() external pure {}
-
-  function myPublicFunction() public {}
-  function myPublicViewFunction() public view {}
-  function myPublicPureFunction() public pure {}
-
-  function myInternalFunction() internal {}
-  function myInternalViewFunction() internal view {}
-  function myInternalPureFunction() internal pure {}
-
-  function myPrivateFunction() private {}
-  function myPrivateViewFunction() private view {}
-  function myPrivatePureFunction() private pure {}
-}
-
-```
-
-#### All units are in order - ^0.6.0
-
-```solidity
-
 pragma solidity ^0.6.0;
 
 import "./some/library.sol";
 import "./some/other-library.sol";
 
-enum MyEnum {
-  Foo,
-  Bar
-}
+    enum MyEnum {
+        Foo,
+        Bar
+    }
 
-struct MyStruct {
-  uint x;
-  uint y;
-}
+    struct MyStruct {
+        uint x;
+        uint y;
+    }
 
 interface IBox {
-  function getValue() public;
-  function setValue(uint) public;
+    function getValue() public;
+    function setValue(uint) public;
 }
 
 library MyLibrary {
-  function add(uint a, uint b, uint c) public returns (uint) {
-    return a + b + c;
-  }
+    function add(uint a, uint b, uint c) public returns (uint) {
+        return a + b + c;
+    }
 }
 
 contract MyContract {
-  using MyLibrary for uint;
+    using MyLibrary for uint;
 
-  struct InnerStruct {
-    bool flag;
-  }
-
-  enum InnerEnum {
-    A, B, C
-  }
+    struct InnerStruct {
+        bool flag;
+    }
 
-  address payable owner;
-  uint public x;
-  uint public y;
+    enum InnerEnum {
+        A, B, C
+    }
 
-  event MyEvent(address a);
+    address payable owner;
+    uint public x;
+    uint public y;
 
-  modifier onlyOwner {
-    require(
-      msg.sender == owner,
-      "Only owner can call this function."
-    );
-    _;
-  }
+    event MyEvent(address a);
 
-  constructor () public {}
+    modifier onlyOwner {
+        require(
+            msg.sender == owner,
+            "Only owner can call this function."
+        );
+        _;
+    }
 
-  receive() external payable {}
+    constructor () public {}
 
-  fallback () external {}
+    fallback () external {}
 
-  function myExternalFunction() external {}
-  function myExternalViewFunction() external view {}
-  function myExternalPureFunction() external pure {}
+    function myExternalFunction() external {}
+    function myExternalViewFunction() external view {}
+    function myExternalPureFunction() external pure {}
 
-  function myPublicFunction() public {}
-  function myPublicViewFunction() public view {}
-  function myPublicPureFunction() public pure {}
+    function myPublicFunction() public {}
+    function myPublicViewFunction() public view {}
+    function myPublicPureFunction() public pure {}
 
-  function myInternalFunction() internal {}
-  function myInternalViewFunction() internal view {}
-  function myInternalPureFunction() internal pure {}
+    function myInternalFunction() internal {}
+    function myInternalViewFunction() internal view {}
+    function myInternalPureFunction() internal pure {}
 
-  function myPrivateFunction() private {}
-  function myPrivateViewFunction() private view {}
-  function myPrivatePureFunction() private pure {}
+    function myPrivateFunction() private {}
+    function myPrivateViewFunction() private view {}
+    function myPrivatePureFunction() private pure {}
 }
 
 ```
@@ -279,66 +138,6 @@ contract MyContract {
 
 ```
 
-#### Use for after state variable
-
-```solidity
-
-contract MyContract {
-  uint public x;
-  
-  using MyMathLib for uint;
-}
-
-```
-
-#### External pure before external view
-
-```solidity
-
-contract MyContract {
-  function myExternalFunction() external {}
-  function myExternalPureFunction() external pure {}
-  function myExternalViewFunction() external view {}
-}
-
-```
-
-#### Public pure before public view
-
-```solidity
-
-contract MyContract {
-  function myPublicFunction() public {}
-  function myPublicPureFunction() public pure {}
-  function myPublicViewFunction() public view {}
-}
-
-```
-
-#### Internal pure before internal view
-
-```solidity
-
-contract MyContract {
-  function myInternalFunction() internal {}
-  function myInternalPureFunction() internal pure {}
-  function myInternalViewFunction() internal view {}
-}
-
-```
-
-#### Private pure before private view
-
-```solidity
-
-contract MyContract {
-  function myPrivateFunction() private {}
-  function myPrivatePureFunction() private pure {}
-  function myPrivateViewFunction() private view {}
-}
-
-```
-
 ## Version
 This rule was introduced in [Solhint 3.2.0](https://github.com/protofire/solhint/tree/v3.2.0)
 
diff --git a/lib/index.js b/lib/index.js
index 1c10e66..6c522eb 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -61,7 +61,7 @@ function processFile(file, config) {
 function processPath(path, config) {
   const ignoreFilter = ignore({ allowRelativePaths: true }).add(config.excludedFiles)
 
-  const allFiles = glob.sync(path, { nodir: true })
+  const allFiles = glob.sync(path, {})
   const files = ignoreFilter.filter(allFiles)
 
   return files.map((curFile) => processFile(curFile, config))
diff --git a/lib/rules/best-practises/no-console.js b/lib/rules/best-practises/no-console.js
index 0f0805e..b21db4a 100644
--- a/lib/rules/best-practises/no-console.js
+++ b/lib/rules/best-practises/no-console.js
@@ -1,5 +1,7 @@
 const BaseChecker = require('../base-checker')
 
+const DEFAULT_SEVERITY = 'error'
+
 const ruleId = 'no-console'
 const meta = {
   type: 'best-practises',
@@ -15,11 +17,11 @@ const meta = {
         },
         {
           description: 'No hardhat/console.sol import statements',
-          code: 'import "hardhat/console.sol"' // eslint-disable-line
+          code: 'import "hardhat/console.sol"',
         },
         {
           description: 'No forge-std console.sol & console2.sol import statements',
-          code: 'import "forge-std/consoleN.sol"' // eslint-disable-line
+          code: 'import "forge-std/consoleN.sol"',
         },
       ],
     },
@@ -27,7 +29,7 @@ const meta = {
 
   isDefault: true,
   recommended: true,
-  defaultSetup: 'error',
+  defaultSetup: [DEFAULT_SEVERITY],
   schema: null,
 }
 
@@ -37,26 +39,31 @@ class NoConsoleLogChecker extends BaseChecker {
   }
 
   ImportDirective(node) {
-    this.isAnImport(node)
-    if (this.isAnImport(node)) {
-      this.error(node, 'No import "hardhat/console.sol" or "forge-std/console.sol" statements') // eslint-disable-line
+    if (this.isConsoleImport(node)) {
+      this.error(node, 'Unexpected import of console file')
     }
   }
 
   FunctionCall(node) {
     if (this.isConsoleLog(node)) {
-      this.error(node, 'No console.logX or console2.log statements')
+      this.error(node, 'Unexpected console statement')
     }
   }
 
   isConsoleLog(node) {
-    return node.expression.expression.name.includes('console')
+    return (
+      node.expression.expression.type === 'Identifier' &&
+      (node.expression.expression.name === 'console' ||
+        node.expression.expression.name === 'console2') &&
+      node.expression.memberName.startsWith('log')
+    )
   }
 
-  isAnImport(node) {
+  isConsoleImport(node) {
     return (
-      node.type === 'ImportDirective' &&
-      (node.path === 'hardhat/console.sol' || node.path.includes('forge-std/console'))
+      node.path === 'hardhat/console.sol' ||
+      node.path === 'forge-std/console.sol' ||
+      node.path === 'forge-std/console2.sol'
     )
   }
 }
diff --git a/package-lock.json b/package-lock.json
index 2a907fe..016fcd1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "solhint",
-  "version": "3.3.8",
+  "version": "3.3.7",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "solhint",
-      "version": "3.3.8",
+      "version": "3.3.7",
       "license": "MIT",
       "dependencies": {
         "@solidity-parser/parser": "^0.14.5",
@@ -38,7 +38,7 @@
         "eslint-config-prettier": "^8.6.0",
         "eslint-plugin-import": "^2.27.4",
         "eslint-plugin-prettier": "^4.2.1",
-        "markdown-table": "^2.0.0",
+        "markdown-table": "^3.0.3",
         "mocha": "^10.2.0",
         "mocha-lcov-reporter": "^1.3.0",
         "nyc": "^15.1.0",
@@ -3215,13 +3215,10 @@
       }
     },
     "node_modules/markdown-table": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
-      "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz",
+      "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==",
       "dev": true,
-      "dependencies": {
-        "repeat-string": "^1.0.0"
-      },
       "funding": {
         "type": "github",
         "url": "https://github.com/sponsors/wooorm"
@@ -4144,15 +4141,6 @@
         "node": ">=4"
       }
     },
-    "node_modules/repeat-string": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
-      "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10"
-      }
-    },
     "node_modules/request": {
       "version": "2.88.2",
       "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
@@ -7456,13 +7444,10 @@
       }
     },
     "markdown-table": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
-      "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==",
-      "dev": true,
-      "requires": {
-        "repeat-string": "^1.0.0"
-      }
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz",
+      "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==",
+      "dev": true
     },
     "mime-db": {
       "version": "1.52.0",
@@ -8135,12 +8120,6 @@
         "es6-error": "^4.0.1"
       }
     },
-    "repeat-string": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
-      "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
-      "dev": true
-    },
     "request": {
       "version": "2.88.2",
       "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
diff --git a/package.json b/package.json
index e769870..a1725dc 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,7 @@
     "eslint-config-prettier": "^8.6.0",
     "eslint-plugin-import": "^2.27.4",
     "eslint-plugin-prettier": "^4.2.1",
-    "markdown-table": "^2.0.0",
+    "markdown-table": "^3.0.3",
     "mocha": "^10.2.0",
     "mocha-lcov-reporter": "^1.3.0",
     "nyc": "^15.1.0",
diff --git a/solhint.js b/solhint.js
old mode 100644
new mode 100755
index 383eed6..d4d968a
--- a/solhint.js
+++ b/solhint.js
@@ -91,13 +91,7 @@ function execMainAction() {
   }
 
   if (printReports(reports, formatterFn)) {
-    if (
-      program.maxWarnings &&
-      reports &&
-      reports.length > 0 &&
-      !reports[0].errorCount &&
-      warningsNumberExceeded
-    ) {
+    if (program.opts().maxWarnings && !reports[0].errorCount && warningsNumberExceeded) {
       console.log(
         'Solhint found more warnings than the maximum specified (maximum: %s)',
         program.opts().maxWarnings


Test patch:
diff --git a/.github/workflows/E2E.yml b/.github/workflows/E2E.yml
index 0ced4ba..36d01f7 100644
--- a/.github/workflows/E2E.yml
+++ b/.github/workflows/E2E.yml
@@ -20,14 +20,10 @@ jobs:
         with:
           node-version: ${{ matrix.node }}
       - uses: actions/checkout@v2
-      - name: install
-        run: npm install --include=dev
-      - name: lint
-        run: npm run lint
-      - name: generate-docs
-        run: npm run docs 
       - name: pack
         run: npm pack
+      - name: lint
+        run: npm install && npm run lint
       - name: install-globally
         run: npm i -g solhint*tgz
       - name: run-e2e-tests
diff --git a/e2e/04-dotSol-on-path/.solhint.json b/e2e/04-dotSol-on-path/.solhint.json
deleted file mode 100644
index 1ee2c69..0000000
--- a/e2e/04-dotSol-on-path/.solhint.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "rules": {
-    "no-empty-blocks": "off"
-  }
-}
diff --git a/e2e/04-dotSol-on-path/contracts/ERC20.sol/ERC20.dbg.js b/e2e/04-dotSol-on-path/contracts/ERC20.sol/ERC20.dbg.js
deleted file mode 100644
index e69de29..0000000
diff --git a/e2e/04-dotSol-on-path/contracts/ERC20.sol/Foo.sol b/e2e/04-dotSol-on-path/contracts/ERC20.sol/Foo.sol
deleted file mode 100644
index 00cbe4c..0000000
--- a/e2e/04-dotSol-on-path/contracts/ERC20.sol/Foo.sol
+++ /dev/null
@@ -1,4 +0,0 @@
-pragma solidity >=0.5.0;
-
-contract Foo {
-}
diff --git a/e2e/test.js b/e2e/test.js
index b4b9399..c614a8e 100644
--- a/e2e/test.js
+++ b/e2e/test.js
@@ -111,14 +111,4 @@ describe('e2e', function() {
       expect(stdout.trim()).to.contain('Code contains empty blocks')
     })
   })
-
-  describe('.sol on path', function() {
-    useFixture('04-dotSol-on-path')
-
-    it('should handle directory names that end with .sol', function() {
-      const { code } = shell.exec('solhint contracts/**/*.sol')
-
-      expect(code).to.equal(0)
-    })
-  })
 })
diff --git a/test/rules/best-practises/no-console.js b/test/rules/best-practises/no-console.js
index 6425796..6b67b2e 100644
--- a/test/rules/best-practises/no-console.js
+++ b/test/rules/best-practises/no-console.js
@@ -3,8 +3,8 @@ const linter = require('../../../lib/index')
 const { assertErrorMessage } = require('../../common/asserts')
 const { funcWith } = require('../../common/contract-builder')
 
-const FUNCTION_CALL_ERROR = 'No console.logX or console2.log statements'
-const IMPORT_ERROR = 'No import "hardhat/console.sol" or "forge-std/console.sol" statements'
+const FUNCTION_CALL_ERROR = 'Unexpected console statement'
+const IMPORT_ERROR = 'Unexpected import of console file'
 
 describe('Linter - no-console', () => {
   it('should raise console.log() is not allowed', () => {
@@ -113,4 +113,27 @@ describe('Linter - no-console', () => {
 
     assert.equal(report.errorCount, 0)
   })
+
+  it('should NOT raise error when method invocation contains "console" string', () => {
+    const code = `
+    contract A {
+      struct Console {
+        uint256 one;
+        uint256 two;
+      }
+      Console[] public consoleTest;
+      Console[] public console;
+      function niceFunction() external {
+        consoleTest.push(0,0);
+        console.push = (1,1);
+      }
+    }
+    `
+
+    const report = linter.processStr(code, {
+      rules: { 'no-console': ['error'] },
+    })
+
+    assert.equal(report.errorCount, 0)
+  })
 })