From bd234a8b8cbad643e326dfade41ba9af4ce535d3 Mon Sep 17 00:00:00 2001 From: Danny Fritz Date: Sun, 11 Sep 2016 21:44:05 -0600 Subject: [PATCH] NEW: Add rule "explicit-member-accessibility" to enforce accessibility modifiers such as public, private, and protected. (refs #4) --- README.md | 6 +- docs/rules/explicit-member-accessibility.md | 42 +++++++++++ lib/rules/explicit-member-accessibility.js | 64 +++++++++++++++++ package.json | 2 +- .../rules/explicit-member-accessibility.js | 70 +++++++++++++++++++ 5 files changed, 178 insertions(+), 6 deletions(-) create mode 100644 docs/rules/explicit-member-accessibility.md create mode 100644 lib/rules/explicit-member-accessibility.js create mode 100644 tests/lib/rules/explicit-member-accessibility.js diff --git a/README.md b/README.md index 9f5177d..2132ea2 100644 --- a/README.md +++ b/README.md @@ -50,8 +50,4 @@ Then configure the rules you want to use under the rules section. ## Supported Rules * `typescript/type-annotation-spacing` - enforces one space after the colon and zero spaces before the colon of a type annotation. - - - - - +* `typescript/explicit-member-accessibility` - enforces accessibility modifiers on class properties and methods. diff --git a/docs/rules/explicit-member-accessibility.md b/docs/rules/explicit-member-accessibility.md new file mode 100644 index 0000000..0144469 --- /dev/null +++ b/docs/rules/explicit-member-accessibility.md @@ -0,0 +1,42 @@ +# Enforces accessibility modifiers on class properties and methods (explicit-member-accessibility) + +Leaving off accessibility modifier and making everything public can make +your interface hard to use by others. +If you make all internal pieces private or protected, your interface will +be easier to use. + +## Rule Details + +This rule aims to make code more readable and explicit about who can use +which properties. + +The following patterns are considered warnings: + +```ts +class Animal { + name: string // No accessibility modifier + getName (): string {} // No accessibility modifier +} +``` + +The following patterns are not warnings: + +```ts +class Animal { + private name: string // explicit accessibility modifier + public getName (): string {} // explicit accessibility modifier +} +``` + +## When Not To Use It + +If you think defaulting to public is a good default, then you will not need +this rule. + +## Further Reading + +* TypeScript [Accessibility Modifiers](https://www.typescriptlang.org/docs/handbook/classes.html#public-private-and-protected-modifiers) + +## Compatibility + +* TSLint: [member-access](http://palantir.github.io/tslint/rules/member-access/) diff --git a/lib/rules/explicit-member-accessibility.js b/lib/rules/explicit-member-accessibility.js new file mode 100644 index 0000000..6890f6d --- /dev/null +++ b/lib/rules/explicit-member-accessibility.js @@ -0,0 +1,64 @@ +/** + * @fileoverview Enforces explicit accessibility modifier for class members + * @author Danny Fritz + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "Enforces explicity accessibility modifiers for class members", + category: "TypeScript" + }, + schema: [] + }, + + create: function(context) { + + //---------------------------------------------------------------------- + // Helpers + //---------------------------------------------------------------------- + + /** + * Checks if a method declaration has an accessibility modifier. + * @param {ASTNode} methodDefinition The node representing a MethodDefinition. + * @returns {void} + * @private + */ + function checkMethodAccessibilityModifier(methodDefinition) { + if (!methodDefinition.accessibility) { + context.report({ + node: methodDefinition, + message: "Missing accessibility modifier on method definition " + methodDefinition.key.name + "." + }); + } + } + + /** + * Checks if property has an accessibility modifier. + * @param {ASTNode} classProperty The node representing a ClassProperty. + * @returns {void} + * @private + */ + function checkPropertyAccessibilityModifier(classProperty) { + if (!classProperty.accessibility) { + context.report({ + node: classProperty, + message: "Missing accessibility modifier on class property " + classProperty.key.name + "." + }); + } + } + + //---------------------------------------------------------------------- + // Public + //---------------------------------------------------------------------- + return { + ClassProperty: checkPropertyAccessibilityModifier, + MethodDefinition: checkMethodAccessibilityModifier + }; + } +}; diff --git a/package.json b/package.json index c3e8e51..b68fac5 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "eslint": "~3.0.0", "eslint-config-eslint": "^3.0.0", "mocha": "^2.4.5", - "typescript-eslint-parser": "~0.1.1" + "typescript-eslint-parser": "^0.4.0" }, "engines": { "node": ">=4" diff --git a/tests/lib/rules/explicit-member-accessibility.js b/tests/lib/rules/explicit-member-accessibility.js new file mode 100644 index 0000000..639e8f7 --- /dev/null +++ b/tests/lib/rules/explicit-member-accessibility.js @@ -0,0 +1,70 @@ +/** + * @fileoverview Enforces explicit accessibility modifiers for class members + * @author Danny Fritz + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +var rule = require("../../../lib/rules/explicit-member-accessibility"), + RuleTester = require("eslint").RuleTester; + + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +var ruleTester = new RuleTester(); +ruleTester.run("explicit-member-accessibility", rule, { + + valid: [ + { + code: ` +class Test { + protected name: string + private x: number + public getX () { + return this.x + } +} + `, + parser: "typescript-eslint-parser" + } + ], + invalid: [ + { + code: ` +class Test { + x: number + public getX () { + return this.x + } +} + `, + parser: "typescript-eslint-parser", + errors: [{ + message: "Missing accessibility modifier on class property x.", + line: 3, + column: 3 + }] + }, + { + code: ` +class Test { + private x: number + getX () { + return this.x + } +} + `, + parser: "typescript-eslint-parser", + errors: [{ + message: "Missing accessibility modifier on method definition getX.", + line: 4, + column: 3 + }] + } + ] +});