diff --git a/README.md b/README.md index 468efd8..cebd853 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,9 @@ In the .soliumrc.json file, add: "zeppelin/no-unused-imports": [ "warning" ], + "zeppelin/private-state-variables-underscore-prefix": [ + "warning" + ], "zeppelin/all-state-variables-private": [ "warning" ] diff --git a/index.js b/index.js index 7417417..001875f 100644 --- a/index.js +++ b/index.js @@ -18,6 +18,7 @@ module.exports = { "no-state-variable-shadowing": require("./rules/no-state-variable-shadowing"), "no-unchecked-send": require("./rules/no-unchecked-send"), "no-unused-imports": require("./rules/no-unused-imports"), + "private-state-variables-underscore-prefix": require("./rules/private-state-variables-underscore-prefix"), "all-state-variables-private": require("./rules/all-state-variables-private") } }; diff --git a/rules/private-state-variables-underscore-prefix.js b/rules/private-state-variables-underscore-prefix.js new file mode 100644 index 0000000..ee01376 --- /dev/null +++ b/rules/private-state-variables-underscore-prefix.js @@ -0,0 +1,38 @@ +/** + * @fileoverview Report private state variables without underscore prefix. + */ + +"use strict"; + +module.exports = { + meta: { + docs: { + recommended: true, + type: "warning", + description: "Report private state variables without underscore prefix" + }, + schema: [] + }, + + create: function(context) { + + function inspectStateVariableDeclaration(emitted) { + if (emitted.exit) { + return; + } + let stateVariable = emitted.node.name; + if ((stateVariable.charAt(0) !== "_") && + (emitted.node.visibility == "private")) { + context.report({ + node: emitted.node, + message: `'${stateVariable}' does not have an underscore as prefix.` + }); + } + + } + + return { + StateVariableDeclaration: inspectStateVariableDeclaration + }; + } +}; diff --git a/test/private-state-variables-underscore-prefix.js b/test/private-state-variables-underscore-prefix.js new file mode 100644 index 0000000..0ee22c3 --- /dev/null +++ b/test/private-state-variables-underscore-prefix.js @@ -0,0 +1,95 @@ +/** + * @fileoverview Tests for private-state-variables-underscore-prefix + */ + +"use strict"; + +const dedent = require("dedent"); +const Solium = require("solium"); +const wrappers = require("./utils/wrappers"); +const addPragma = wrappers.addPragma; + +const userConfig = { + rules: { + "zeppelin/private-state-variables-underscore-prefix": 1 + } +}; + +describe("[RULE] private-state-variables-underscore-prefix: Rejections", function() { + + afterEach(function(done) { + Solium.reset(); + done(); + }); + + it("should reject private state variables without underscore prefix", function(done) { + const code = dedent` + contract TestContract { + bool private variableWithoutUnderscorePrefix = false; + }`, + errors = Solium.lint(addPragma(code), userConfig); + + errors.should.be.instanceof(Array); + errors.length.should.equal(1); + errors[0].message.should.equal( + "'variableWithoutUnderscorePrefix' does not have an underscore as prefix."); + done(); + }); +}); + +describe("[RULE] private-state-variables-underscore-prefix: Acceptances", function() { + + afterEach(function(done) { + Solium.reset(); + done(); + }); + + it("should accept private state variables with underscore prefix", function(done) { + const code = dedent` + contract TestContract { + bool private _variableWithUnderscorePrefix = false; + }`, + errors = Solium.lint(addPragma(code), userConfig); + + errors.should.deepEqual([]); + + done(); + }); + + it("should accept public state variables", function(done) { + const code = dedent` + contract TestContract { + bool public publicStateVariable = false; + }`, + errors = Solium.lint(addPragma(code), userConfig); + + errors.should.deepEqual([]); + + done(); + }); + + it("should accept internal state variables", function(done) { + const code = dedent` + contract TestContract { + bool internal internalStateVariable = false; + }`, + errors = Solium.lint(addPragma(code), userConfig); + + errors.should.deepEqual([]); + + done(); + }); + + it("should accept state variables with default visibility", function(done) { + const code = dedent` + contract TestContract { + bool stateVariableWithDefaultVisibility = false; + }`, + errors = Solium.lint(addPragma(code), userConfig); + + errors.should.deepEqual([]); + + done(); + }); + +});