Skip to content

Commit 5919570

Browse files
committed
NEW: Add rule "member-access" to enforce visibility modifiers such as public, private, protected, and static. (refs bradzacher#4)
1 parent 65f1821 commit 5919570

File tree

4 files changed

+193
-5
lines changed

4 files changed

+193
-5
lines changed

README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,4 @@ Then configure the rules you want to use under the rules section.
5050
## Supported Rules
5151

5252
* `typescript/type-annotation-spacing` - enforces one space after the colon and zero spaces before the colon of a type annotation.
53-
54-
55-
56-
57-
53+
* `typescript/member-access` - enforces visibility modifiers on class properties and methods.

docs/rules/member-access.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Enforces visibility modifier on class properties and methods (method-access)
2+
3+
Leaving off visibility modifier and making everything public can make
4+
your interface hard to use by others.
5+
If you make all internal pieces private or protected, your interface will
6+
be easier to use.
7+
8+
## Rule Details
9+
10+
This rule aims to make code more readable and explicit about who can use
11+
which properties.
12+
13+
The following patterns are considered warnings:
14+
15+
```ts
16+
class Animal {
17+
name: string // No visibility modifier
18+
getName (): string {} // No visibility modifier
19+
}
20+
```
21+
22+
The following patterns are not warnings:
23+
24+
```ts
25+
class Animal {
26+
private name: string // explicit visibility modifier
27+
public getName (): string {} // explicit visibility modifier
28+
}
29+
```
30+
31+
## When Not To Use It
32+
33+
If you think defaulting to public is a good default then you will not need
34+
this rule.
35+
36+
## Further Reading
37+
38+
* TypeScript [Visibility Modifiers](https://www.typescriptlang.org/docs/handbook/classes.html#public-private-and-protected-modifiers)
39+
40+
## Compatibility
41+
42+
* TSLint: [member-access](http://palantir.github.io/tslint/rules/member-access/)

lib/rules/member-access.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/**
2+
* @fileoverview Enforces explicit visibility modifier for class members
3+
* @author Danny Fritz
4+
*/
5+
"use strict";
6+
7+
//------------------------------------------------------------------------------
8+
// Rule Definition
9+
//------------------------------------------------------------------------------
10+
11+
module.exports = {
12+
meta: {
13+
docs: {
14+
description: "Enforces explicity visibility modifiers for class members",
15+
category: "TypeScript"
16+
},
17+
schema: []
18+
},
19+
20+
create: function(context) {
21+
22+
var sourceCode = context.getSourceCode();
23+
var visibilityRegExp = /^(public)|(private)|(static)|(protected)/;
24+
25+
//----------------------------------------------------------------------
26+
// Helpers
27+
//----------------------------------------------------------------------
28+
29+
/**
30+
* Checks if a string starts with a visibility modifier.
31+
* @param {string} nodeText The text representing a node.
32+
* @returns {boolean} true if it has a visibility decorator
33+
* @private
34+
*/
35+
function hasVisibilityDeclaration(nodeText) {
36+
if (visibilityRegExp.test(nodeText)) {
37+
return true;
38+
}
39+
return false;
40+
}
41+
42+
/**
43+
* Checks if a method declaration has visibility modifier.
44+
* @param {ASTNode} methodDefinition The node representing a MethodDefinition.
45+
* @returns {void}
46+
* @private
47+
*/
48+
function checkMethodVisibilityModifier(methodDefinition) {
49+
if (!hasVisibilityDeclaration(sourceCode.getText(methodDefinition))) {
50+
context.report({
51+
node: methodDefinition,
52+
message: "Missing visibility modifier on method definition " + methodDefinition.key.name + "."
53+
});
54+
}
55+
}
56+
57+
/**
58+
* Checks if property has visibility modifiers.
59+
* @param {ASTNode} classProperty The node representing a ClassProperty.
60+
* @returns {void}
61+
* @private
62+
*/
63+
function checkPropertyVisibilityModifier(classProperty) {
64+
if (!hasVisibilityDeclaration(sourceCode.getText(classProperty))) {
65+
context.report({
66+
node: classProperty,
67+
message: "Missing visibility modifier on class property " + classProperty.key.name + "."
68+
});
69+
}
70+
}
71+
72+
//----------------------------------------------------------------------
73+
// Public
74+
//----------------------------------------------------------------------
75+
return {
76+
ClassProperty: checkPropertyVisibilityModifier,
77+
MethodDefinition: checkMethodVisibilityModifier
78+
};
79+
}
80+
};

tests/lib/rules/member-access.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* @fileoverview Enforces explicit visibility modifiers for class members
3+
* @author Danny Fritz
4+
*/
5+
"use strict";
6+
7+
//------------------------------------------------------------------------------
8+
// Requirements
9+
//------------------------------------------------------------------------------
10+
11+
var rule = require("../../../lib/rules/member-access"),
12+
RuleTester = require("eslint").RuleTester;
13+
14+
15+
//------------------------------------------------------------------------------
16+
// Tests
17+
//------------------------------------------------------------------------------
18+
19+
var ruleTester = new RuleTester();
20+
ruleTester.run("member-access", rule, {
21+
22+
valid: [
23+
{
24+
code: `
25+
class Test {
26+
static name: string
27+
private x: number
28+
public getX () {
29+
return this.x
30+
}
31+
}
32+
`,
33+
parser: "typescript-eslint-parser"
34+
}
35+
],
36+
invalid: [
37+
{
38+
code: `
39+
class Test {
40+
x: number
41+
public getX () {
42+
return this.x
43+
}
44+
}
45+
`,
46+
parser: "typescript-eslint-parser",
47+
errors: [{
48+
message: "Missing visibility modifier on class property x.",
49+
line: 3,
50+
column: 3
51+
}]
52+
},
53+
{
54+
code: `
55+
class Test {
56+
private x: number
57+
getX () {
58+
return this.x
59+
}
60+
}
61+
`,
62+
parser: "typescript-eslint-parser",
63+
errors: [{
64+
message: "Missing visibility modifier on method definition getX.",
65+
line: 4,
66+
column: 3
67+
}]
68+
}
69+
]
70+
});

0 commit comments

Comments
 (0)