Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(eslint-plugin): [member-accessibility] add more options #322

Merged
merged 17 commits into from Apr 7, 2019
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -65,7 +65,7 @@
"glob": "7.1.2",
"husky": "^1.3.1",
"isomorphic-fetch": "^2.2.1",
"jest": "24.1.0",
"jest": "24.3.0",
"lerna": "^3.10.5",
"lint-staged": "8.1.0",
"lodash.isplainobject": "4.0.6",
Expand Down
235 changes: 227 additions & 8 deletions packages/eslint-plugin/docs/rules/explicit-member-accessibility.md
Expand Up @@ -10,28 +10,247 @@ be easier to use.
This rule aims to make code more readable and explicit about who can use
which properties.

The following patterns are considered warnings:
## Options

```ts
type AccessibilityLevel =
| 'explicit' // require an accessor (including public)
| 'no-public' // don't require public
| 'off'; // don't check

interface Config {
accessibility?: AccessibilityLevel;
overrides?: {
accessors?: AccessibilityLevel;
constructors?: AccessibilityLevel;
methods?: AccessibilityLevel;
properties?: AccessibilityLevel;
parameterProperties?: AccessibilityLevel;
};
}
```

Default config:

```JSON
{ "accessibility": "explicit" }
```

This rule in it's default state requires no configuration and will enforce that every class member has an accessibility modifier. If you would like to allow for some implicit public members then you have the following options:
A possible configuration could be:

```ts
{
accessibility: 'explicit',
overrides {
accessors: 'explicit',
constructors: 'no-public',
methods: 'explicit',
properties: 'off',
parameterProperties: 'explicit'
}
}
```

The following patterns are considered incorrect code if no options are provided:

```ts
class Animal {
constructor(name) {
// No accessibility modifier
this.animalName = name;
}
animalName: string; // No accessibility modifier
get name(): string {
// No accessibility modifier
return this.animalName;
}
set name(value: string) {
// No accessibility modifier
this.animalName = value;
}
walk() {
// method
}
}
```

The following patterns are considered correct with the default options `{ accessibility: 'explicit' }`:

```ts
class Animal {
public constructor(public breed, animalName) {
// Parameter property and constructor
this.animalName = name;
}
private animalName: string; // Property
get name(): string {
// get accessor
return this.animalName;
}
set name(value: string) {
// set accessor
this.animalName = value;
}
public walk() {
// method
}
}
```

The following patterns are considered incorrect with the accessibility set to **no-public** `[{ accessibility: 'no-public' }]`:

```ts
class Animal {
public constructor(public breed, animalName) {
// Parameter property and constructor
this.animalName = name;
}
public animalName: string; // Property
public get name(): string {
// get accessor
return this.animalName;
}
public set name(value: string) {
// set accessor
this.animalName = value;
}
public walk() {
// method
}
}
```

The following patterns are considered correct with the accessibility set to **no-public** `[{ accessibility: 'no-public' }]`:

```ts
class Animal {
constructor(protected breed, animalName) {
// Parameter property and constructor
this.name = name;
}
private animalName: string; // Property
get name(): string {
// get accessor
return this.animalName;
}
private set name(value: string) {
// set accessor
this.animalName = value;
}
protected walk() {
// method
}
}
```

### Overrides

There are three ways in which an override can be used.

- To disallow the use of public on a given member.
- To enforce explicit member accessibility when the root has allowed implicit public accessibility
- To disable any checks on given member type

#### Disallow the use of public on a given member

e.g. `[ { overrides: { constructor: 'no-public' } } ]`

The following patterns are considered incorrect with the example override

```ts
class Animal {
public constructor(protected animalName) {}
public get name() {
return this.animalName;
}
}
```

The following patterns are considered correct with the example override

```ts
class Animal {
constructor(protected animalName) {}
public get name() {
return this.animalName;
}
}
```

#### Require explicit accessibility for a given member

e.g. `[ { accessibility: 'no-public', overrides: { properties: 'explicit' } } ]`

The following patterns are considered incorrect with the example override

```ts
class Animal {
constructor(protected animalName) {}
get name() {
return this.animalName;
}
protected set name(value: string) {
this.animalName = value;
}
legs: number;
private hasFleas: boolean;
}
```

The following patterns are considered correct with the example override

```ts
class Animal {
constructor(protected animalName) {}
get name() {
return this.animalName;
}
protected set name(value: string) {
this.animalName = value;
}
public legs: number;
private hasFleas: boolean;
}
```

#### Disable any checks on given member type

e.g. `[{ overrides: { accessors : 'off' } } ]`

As no checks on the overridden member type are performed all permutations of visibility are permitted for that member type

The follow pattern is considered incorrect for the given configuration

```ts
class Animal {
name: string; // No accessibility modifier
getName(): string {} // No accessibility modifier
constructor(protected animalName) {}
public get name() {
return this.animalName;
}
get legs() {
return this.legCount;
}
}
```

The following patterns are not warnings:
The following patterns are considered correct with the example override

```ts
class Animal {
private name: string; // explicit accessibility modifier
public getName(): string {} // explicit accessibility modifier
public constructor(protected animalName) {}
public get name() {
return this.animalName;
}
get legs() {
return this.legCount;
}
}
```

## When Not To Use It

If you think defaulting to public is a good default, then you will not need
this rule.
If you think defaulting to public is a good default, then you should consider using the `no-public` setting. If you want to mix implicit and explicit public members then disable this rule.

## Further Reading

Expand Down