Skip to content

Commit

Permalink
feat: support valid flow strict annotation (#414)
Browse files Browse the repository at this point in the history
* Support flow strict

* Fix replacement fixer

* docs: generate docs

* Update document

* docs: generate docs

* Update README for strict flow annotation

* docs: generate docs
  • Loading branch information
xunuoi authored and gajus committed Jun 24, 2019
1 parent 55e110c commit e36b920
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .README/rules/require-valid-file-annotation.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ This rule has an object option:
* `"line"`: Require single line annotations (i.e. `// @flow`).
* `"block"`: Require block annotations (i.e. `/* @flow */`).

* `"strict"` - Enforce a strict flow file annotation.
* `false` (default): strict flow annotation is not required.
* `true`: Require strict flow annotation (i.e. `// @flow strict`).

```js
{
"rules": {
Expand All @@ -34,6 +38,7 @@ This rule has an object option:
2,
"always", {
"annotationStyle": "block"
"strict": true,
}
]
}
Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3028,6 +3028,10 @@ This rule has an object option:
* `"line"`: Require single line annotations (i.e. `// @flow`).
* `"block"`: Require block annotations (i.e. `/* @flow */`).

* `"strict"` - Enforce a strict flow file annotation.
* `false` (default): strict flow annotation is not required.
* `true`: Require strict flow annotation (i.e. `// @flow strict`).

```js
{
"rules": {
Expand All @@ -3044,6 +3048,7 @@ This rule has an object option:
2,
"always", {
"annotationStyle": "block"
"strict": true,
}
]
}
Expand Down Expand Up @@ -3087,6 +3092,14 @@ a;
// @flow
// Message: Flow file annotation style must be `/* @flow */`

// Options: ["always",{"annotationStyle":"block"}]
// @flow
// Message: Flow file annotation style must be `/* @flow */`

// Options: ["always",{"annotationStyle":"line","strict":true}]
// @flow
// Message: Strict Flow file annotation is required, should be `// @flow strict`

// Options: ["always",{"annotationStyle":"line"}]
/* @noflow */
// Message: Flow file annotation style must be `// @noflow`
Expand All @@ -3102,6 +3115,16 @@ a;
// Options: ["always",{"annotationStyle":"block"}]
a;
// Message: Flow file annotation is missing.

// Options: ["always",{"annotationStyle":"line","strict":true}]
a;
// Message: Flow file annotation is missing.

// Options: ["always",{"annotationStyle":"line","strict":true}]
// @flow
a;
b;
// Message: Strict Flow file annotation is required, should be `// @flow strict`
```
The following patterns are not considered problems:
Expand Down Expand Up @@ -3139,6 +3162,9 @@ a;
// Options: ["always",{"annotationStyle":"line"}]
// @flow

// Options: ["always",{"annotationStyle":"line","strict":true}]
// @flow strict

// Options: ["never",{"annotationStyle":"none"}]
// @function

Expand Down
38 changes: 35 additions & 3 deletions src/rules/requireValidFileAnnotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
} from '../utilities';

const defaults = {
annotationStyle: 'none'
annotationStyle: 'none',
strict: false
};

const looksLikeFlowFileAnnotation = (comment) => {
Expand All @@ -24,6 +25,10 @@ const checkAnnotationSpelling = (comment) => {
return /@[a-z]+\b/.test(comment) && fuzzyStringMatch(comment.replace(/no/i, ''), '@flow', 0.2);
};

const isFlowStrict = (comment) => {
return /@flow\sstrict\b/.test(comment);
};

const schema = [
{
enum: ['always', 'never'],
Expand All @@ -35,6 +40,10 @@ const schema = [
annotationStyle: {
enum: ['none', 'line', 'block'],
type: 'string'
},
strict: {
enum: [true, false],
type: 'boolean'
}
},
type: 'object'
Expand All @@ -44,19 +53,32 @@ const schema = [
const create = (context) => {
const always = context.options[0] === 'always';
const style = _.get(context, 'options[1].annotationStyle', defaults.annotationStyle);
const flowStrict = _.get(context, 'options[1].strict', defaults.strict);

return {
Program (node) {
const firstToken = node.tokens[0];

const addAnnotation = () => {
return (fixer) => {
const annotation = ['line', 'none'].includes(style) ? '// @flow\n' : '/* @flow */\n';
let annotation;
if (flowStrict) {
annotation = ['line', 'none'].includes(style) ? '// @flow strict\n' : '/* @flow strict */\n';
} else {
annotation = ['line', 'none'].includes(style) ? '// @flow\n' : '/* @flow */\n';
}

return fixer.replaceTextRange([node.start, node.start], annotation);
};
};

const addStrictAnnotation = () => {
return (fixer) => {
const annotation = ['line', 'none'].includes(style) ? '// @flow strict\n' : '/* @flow strict */\n';

return fixer.replaceTextRange([node.start, node.range[0]], annotation);
};
};

const potentialFlowFileAnnotation = _.find(context.getAllComments(), (comment) => {
return looksLikeFlowFileAnnotation(comment.value);
});
Expand All @@ -72,6 +94,16 @@ const create = (context) => {

context.report(potentialFlowFileAnnotation, 'Flow file annotation style must be ' + str);
}
if (flowStrict) {
if (!isFlowStrict(potentialFlowFileAnnotation.value.trim())) {
const str = style === 'line' ? '`// @flow strict`' : '`/* @flow strict */`';
context.report({
fix: addStrictAnnotation(),
message: 'Strict Flow file annotation is required, should be ' + str,
node
});
}
}
} else if (checkAnnotationSpelling(potentialFlowFileAnnotation.value.trim())) {
context.report(potentialFlowFileAnnotation, 'Misspelled or malformed Flow file annotation.');
} else {
Expand Down
71 changes: 71 additions & 0 deletions tests/rules/assertions/requireValidFileAnnotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,35 @@ export default {
}
]
},
{
code: '// @flow',
errors: [
{
message: 'Flow file annotation style must be `/* @flow */`'
}
],
options: [
'always',
{
annotationStyle: 'block'
}
]
},
{
code: '// @flow',
errors: [
{
message: 'Strict Flow file annotation is required, should be `// @flow strict`'
}
],
options: [
'always',
{
annotationStyle: 'line',
strict: true
}
]
},
{
code: '/* @noflow */',
errors: [
Expand Down Expand Up @@ -149,6 +178,38 @@ export default {
}
],
output: '/* @flow */\na;'
},
{
code: 'a;',
errors: [
{
message: 'Flow file annotation is missing.'
}
],
options: [
'always',
{
annotationStyle: 'line',
strict: true
}
],
output: '// @flow strict\na;'
},
{
code: '// @flow\na;\nb;',
errors: [
{
message: 'Strict Flow file annotation is required, should be `// @flow strict`'
}
],
options: [
'always',
{
annotationStyle: 'line',
strict: true
}
],
output: '// @flow strict\na;\nb;'
}
],
misconfigured: [
Expand Down Expand Up @@ -257,6 +318,16 @@ export default {
}
]
},
{
code: '// @flow strict',
options: [
'always',
{
annotationStyle: 'line',
strict: true
}
]
},
{
code: '// @function',
options: [
Expand Down

0 comments on commit e36b920

Please sign in to comment.