Repository: protofire/solhint (js)

Issue:
no-empty-blocks should not run on default-functions
When a default-function is used, its common to not do anything in the function itself.

```solidity
    function() public payable {
        // got money
    }
```

Solhint currently gives the warning `Code contains empty block  no-empty-blocks`.

Pull request description:
Ignore empty blocks in fallback functions
Closes #31.

Patch:
diff --git a/lib/common/ast-types.js b/lib/common/ast-types.js
new file mode 100644
index 0000000..6647c19
--- /dev/null
+++ b/lib/common/ast-types.js
@@ -0,0 +1,14 @@
+const { typeOf } = require('./tree-traversing')
+
+function isFallbackFunction(ctx) {
+  return ctx.children && ctx.children[1] && ctx.children[1].constructor.name !== 'IdentifierContext'
+}
+
+function isFunctionDefinition(ctx) {
+  return typeOf(ctx) === 'functionDefinition'
+}
+
+module.exports = {
+  isFallbackFunction,
+  isFunctionDefinition
+}
diff --git a/lib/rules/align/bracket-align.js b/lib/rules/align/bracket-align.js
index 3200660..00ee05a 100644
--- a/lib/rules/align/bracket-align.js
+++ b/lib/rules/align/bracket-align.js
@@ -1,7 +1,7 @@
 const _ = require('lodash')
 const BaseChecker = require('./../base-checker')
 const { hasSpaceBefore, onSameLine, prevToken, startOf } = require('./../../common/tokens')
-const { typeOf } = require('./../../common/tree-traversing')
+const { isFunctionDefinition } = require('./../../common/ast-types')
 
 const ruleId = 'bracket-align'
 const meta = {
@@ -83,10 +83,6 @@ class Block {
     return bracketCtx ? this._makeBracketObj(bracketCtx) : null
   }
 
-  isFunctionDefinition() {
-    return typeOf(this.ctx.parentCtx) === 'functionDefinition'
-  }
-
   _openBracketCtx() {
     const children = this.ctx.children
     const openBrackets = children && children.filter(i => i.getText() === '{')
@@ -95,7 +91,9 @@ class Block {
   }
 
   _makeBracketObj(ctx) {
-    return this.isFunctionDefinition() ? new FunctionOpenBracket(ctx) : new UsualOpenBracket(ctx)
+    return isFunctionDefinition(this.ctx.parentCtx)
+      ? new FunctionOpenBracket(ctx)
+      : new UsualOpenBracket(ctx)
   }
 }
 
diff --git a/lib/rules/best-practises/no-empty-blocks.js b/lib/rules/best-practises/no-empty-blocks.js
index 78c9e5d..1dba29b 100644
--- a/lib/rules/best-practises/no-empty-blocks.js
+++ b/lib/rules/best-practises/no-empty-blocks.js
@@ -1,5 +1,6 @@
 const BaseChecker = require('./../base-checker')
 const { typeOf } = require('./../../common/tree-traversing')
+const { isFallbackFunction, isFunctionDefinition } = require('./../../common/ast-types')
 
 const ONLY_BRACKETS_LENGTH = 2
 const EMPTY_STRUCT_LENGTH = 4
@@ -27,6 +28,12 @@ class NoEmptyBlocksChecker extends BaseChecker {
   }
 
   exitBlock(ctx) {
+    const isFallbackFunctionBlock =
+      isFunctionDefinition(ctx.parentCtx) && isFallbackFunction(ctx.parentCtx)
+    if (isFallbackFunctionBlock) {
+      // ignore empty blocks in fallback functions
+      return
+    }
     this._validateChildrenCount(ctx, ONLY_BRACKETS_LENGTH)
   }
 


Test patch:
diff --git a/test/rules/best-practises/no-empty-blocks.js b/test/rules/best-practises/no-empty-blocks.js
index 76ef8f4..d94b43b 100644
--- a/test/rules/best-practises/no-empty-blocks.js
+++ b/test/rules/best-practises/no-empty-blocks.js
@@ -4,7 +4,6 @@ const { contractWith, funcWith } = require('./../../common/contract-builder')
 
 describe('Linter - no-empty-blocks', () => {
   const EMPTY_BLOCKS = [
-    contractWith('function () public payable {}'),
     funcWith('if (a < b) {  }'),
     contractWith('struct Abc {  }'),
     contractWith('enum Abc {  }'),
@@ -42,6 +41,15 @@ describe('Linter - no-empty-blocks', () => {
     })
   )
 
+  it('should not raise error for default function', () => {
+    const defaultFunction = contractWith('function () public payable {}')
+    const report = linter.processStr(defaultFunction, {
+      rules: { 'no-empty-blocks': 'warn' }
+    })
+
+    assertNoWarnings(report)
+  })
+
   function label(data) {
     const items = data.split('\n')
     const lastItemIndex = items.length - 1