Skip to content

Commit

Permalink
feat: Add require-read-only-array rule (gajus#236)
Browse files Browse the repository at this point in the history
This rule enforces use of `$ReadOnlyArray` instead of `Array` or array
shorthand notation.
  • Loading branch information
pnevyk committed Oct 1, 2017
1 parent 0cb7f02 commit e659da5
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 0 deletions.
1 change: 1 addition & 0 deletions .README/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ When `true`, only checks files with a [`@flow` annotation](http://flowtype.org/d
{"gitdown": "include", "file": "./rules/no-weak-types.md"}
{"gitdown": "include", "file": "./rules/object-type-delimiter.md"}
{"gitdown": "include", "file": "./rules/require-parameter-type.md"}
{"gitdown": "include", "file": "./rules/require-read-only-array.md"}
{"gitdown": "include", "file": "./rules/require-return-type.md"}
{"gitdown": "include", "file": "./rules/require-valid-file-annotation.md"}
{"gitdown": "include", "file": "./rules/require-variable-type.md"}
Expand Down
16 changes: 16 additions & 0 deletions .README/rules/require-read-only-array.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
### `require-read-only-array`

_The `--fix` option on the command line automatically fixes problems reported by this rule._

Requires use of [`$ReadOnlyArray`](https://github.com/facebook/flow/blob/v0.46.0/lib/core.js#L185) instead of just `Array` or array [shorthand notation](https://flow.org/en/docs/types/arrays/#toc-array-type-shorthand-syntax). `$ReadOnlyArray` is immutable array collection type and the superclass of Array and tuple types in Flow. Use of `$ReadOnlyArray` instead of `Array` can solve some "problems" in typing with Flow (e.g., [1](https://github.com/facebook/flow/issues/3425), [2](https://github.com/facebook/flow/issues/4251)).

General reasons for using immutable data structures:

* They are simpler to construct, test, and use
* They help to avoid temporal coupling
* Their usage is side-effect free (no defensive copies)
* Identity mutability problem is avoided
* They always have failure atomicity
* They are much easier to cache

<!-- assertions requireReadOnlyArray -->
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import noUnusedExpressions from './rules/noUnusedExpressions';
import noWeakTypes from './rules/noWeakTypes';
import objectTypeDelimiter from './rules/objectTypeDelimiter';
import requireParameterType from './rules/requireParameterType';
import requireReadOnlyArray from './rules/requireReadOnlyArray';
import requireReturnType from './rules/requireReturnType';
import requireValidFileAnnotation from './rules/requireValidFileAnnotation';
import requireVariableType from './rules/requireVariableType';
Expand All @@ -37,6 +38,7 @@ const rules = {
'no-weak-types': noWeakTypes,
'object-type-delimiter': objectTypeDelimiter,
'require-parameter-type': requireParameterType,
'require-read-only-array': requireReadOnlyArray,
'require-return-type': requireReturnType,
'require-valid-file-annotation': requireValidFileAnnotation,
'require-variable-type': requireVariableType,
Expand Down Expand Up @@ -74,6 +76,7 @@ export default {
'no-weak-types': 0,
'object-type-delimiter': 0,
'require-parameter-type': 0,
'require-read-only-array': 0,
'require-return-type': 0,
'require-variable-type': 0,
semi: 0,
Expand Down
33 changes: 33 additions & 0 deletions src/rules/requireReadOnlyArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const schema = [];

const create = (context) => {
return {
ArrayTypeAnnotation (node) {
context.report({
fix (fixer) {
const rawElementType = context.getSourceCode().getText(node.elementType);

return fixer.replaceText(node, '$ReadOnlyArray<' + rawElementType + '>');
},
message: 'Use "$ReadOnlyArray" instead of array shorthand notation',
node
});
},
GenericTypeAnnotation (node) {
if (node.id.name === 'Array') {
context.report({
fix (fixer) {
return fixer.replaceText(node.id, '$ReadOnlyArray');
},
message: 'Use "$ReadOnlyArray" instead of "Array"',
node
});
}
}
};
};

export default {
create,
schema
};
19 changes: 19 additions & 0 deletions tests/rules/assertions/requireReadOnlyArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export default {
invalid: [
{
code: 'type X = Array<string>',
errors: [{message: 'Use "$ReadOnlyArray" instead of "Array"'}],
output: 'type X = $ReadOnlyArray<string>'
},
{
code: 'type X = string[]',
errors: [{message: 'Use "$ReadOnlyArray" instead of array shorthand notation'}],
output: 'type X = $ReadOnlyArray<string>'
}
],
valid: [
{
code: 'type X = $ReadOnlyArray<string>'
}
]
};
1 change: 1 addition & 0 deletions tests/rules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const reportingRules = [
'no-weak-types',
'object-type-delimiter',
'require-parameter-type',
'require-read-only-array',
'require-return-type',
'require-valid-file-annotation',
'require-variable-type',
Expand Down

0 comments on commit e659da5

Please sign in to comment.