Skip to content

Commit

Permalink
feat: Rule schemas for validation. (#252)
Browse files Browse the repository at this point in the history
* chore: Test rule schemas.

* chore: Add misconfiguration tests for the "type-id-match" rule.

* chore: Add misconfiguration tests for the "require-valid-file-annotation" rule.

And fix the schema accordingly.

* refactor: Specify enum types in rule schemas.

* chore: Create a schema for the "boolean-style" rule.

* refactor: Export the schema for the "define-flow-type" rule.

* chore: Create a schema for the "delimiter-dangle" rule.

* chore: Create a schema for the "generic-spacing" rule.

* chore: Create a schema for the "no-dupe-keys" rule.

* chore: Create a schema for the "no-primitive-constructor-types" rule.

* chore: Create a schema for the "no-types-missing-file-annotation" rule.

* chore: Create a schema for the "no-weak-types" rule.

* chore: Create a schema for the "require-parameter-type" rule.

* chore: Create a schema for the "require-return-type" rule.

* chore: Create a schema for the "require-variable-type" rule.

* chore: Create a schema for the "semi" rule.

* chore: Create a schema for the "sort-keys" rule.

* chore: Create a schema for the "space-after-type-colon" rule.

* chore: Create a schema for the "space-before-generic-bracket" rule.

* chore: Create a schema for the "space-before-type-colon" rule.

* chore: Create a schema for the "union-intersection-spacing" rule.

* refactor: Export the schema for the "use-flow-type" rule.

* chore: Create a schema for the "valid-syntax" rule.

* fix: Don't decorate the "no-types-missing-file-annotation" rule.

* refactor: Use ajv instead of is-my-json-valid.

* refactor: Sort rules by name.
  • Loading branch information
SamirTalwar authored and gajus committed Jul 11, 2017
1 parent 996acd3 commit b1409e3
Show file tree
Hide file tree
Showing 42 changed files with 1,358 additions and 71 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -9,6 +9,7 @@
},
"description": "Flowtype linting rules for ESLint.",
"devDependencies": {
"ajv": "^5.2.1",
"babel-cli": "^6.14.0",
"babel-eslint": "^6.1.2",
"babel-plugin-add-module-exports": "^0.2.1",
Expand Down
33 changes: 14 additions & 19 deletions src/index.js
@@ -1,28 +1,28 @@
import _ from 'lodash';
import {checkFlowFileAnnotation} from './utilities';
import recommended from './configs/recommended.json';
import booleanStyle from './rules/booleanStyle';
import defineFlowType from './rules/defineFlowType';
import delimiterDangle from './rules/delimiterDangle';
import genericSpacing from './rules/genericSpacing';
import noWeakTypes from './rules/noWeakTypes';
import noDupeKeys from './rules/noDupeKeys';
import noPrimitiveConstructorTypes from './rules/noPrimitiveConstructorTypes';
import noTypesMissingFileAnnotation from './rules/noTypesMissingFileAnnotation';
import noWeakTypes from './rules/noWeakTypes';
import objectTypeDelimiter from './rules/objectTypeDelimiter';
import requireParameterType from './rules/requireParameterType';
import requireReturnType from './rules/requireReturnType';
import requireValidFileAnnotation from './rules/requireValidFileAnnotation';
import requireVariableType from './rules/requireVariableType';
import semi from './rules/semi';
import sortKeys from './rules/sortKeys';
import spaceAfterTypeColon from './rules/spaceAfterTypeColon';
import spaceBeforeGenericBracket from './rules/spaceBeforeGenericBracket';
import spaceBeforeTypeColon from './rules/spaceBeforeTypeColon';
import unionIntersectionSpacing from './rules/unionIntersectionSpacing';
import typeIdMatch from './rules/typeIdMatch';
import unionIntersectionSpacing from './rules/unionIntersectionSpacing';
import useFlowType from './rules/useFlowType';
import validSyntax from './rules/validSyntax';
import booleanStyle from './rules/booleanStyle';
import delimiterDangle from './rules/delimiterDangle';
import noDupeKeys from './rules/noDupeKeys';
import noPrimitiveConstructorTypes from './rules/noPrimitiveConstructorTypes';
import sortKeys from './rules/sortKeys';
import objectTypeDelimiter from './rules/objectTypeDelimiter';
import recommended from './configs/recommended.json';
import {checkFlowFileAnnotation} from './utilities';

const rules = {
'boolean-style': booleanStyle,
Expand Down Expand Up @@ -54,19 +54,14 @@ export default {
recommended
},
rules: _.mapValues(rules, (rule, key) => {
// Support current and deprecated rule formats
if (_.isPlainObject(rule)) {
return {
...rule,
create: _.partial(checkFlowFileAnnotation, rule.create)
};
}

if (key === 'no-types-missing-file-annotation') {
return rule;
}

return _.partial(checkFlowFileAnnotation, rule);
return {
...rule,
create: _.partial(checkFlowFileAnnotation, rule.create)
};
}),
rulesConfig: {
'boolean-style': 0,
Expand Down
14 changes: 13 additions & 1 deletion src/rules/booleanStyle.js
@@ -1,4 +1,11 @@
export default (context) => {
const schema = [
{
enum: ['bool', 'boolean'],
type: 'string'
}
];

const create = (context) => {
const longForm = (context.options[0] || 'boolean') === 'boolean';

return {
Expand Down Expand Up @@ -27,3 +34,8 @@ export default (context) => {
}
};
};

export default {
create,
schema
};
9 changes: 7 additions & 2 deletions src/rules/defineFlowType.js
@@ -1,6 +1,6 @@
export const schema = [];
const schema = [];

export default (context) => {
const create = (context) => {
let globalScope;

// do nearly the same thing that eslint does for config globals
Expand Down Expand Up @@ -62,3 +62,8 @@ export default (context) => {
}
};
};

export default {
create,
schema
};
14 changes: 13 additions & 1 deletion src/rules/delimiterDangle.js
@@ -1,6 +1,13 @@
import _ from 'lodash';

export default (context) => {
const schema = [
{
enum: ['always', 'always-multiline', 'only-multiline', 'never'],
type: 'string'
}
];

const create = (context) => {
const option = context.options[0] || 'never';
const sourceCode = context.getSourceCode();

Expand Down Expand Up @@ -103,3 +110,8 @@ export default (context) => {
}
};
};

export default {
create,
schema
};
14 changes: 13 additions & 1 deletion src/rules/genericSpacing.js
@@ -1,6 +1,13 @@
import {spacingFixers} from './../utilities';

export default (context) => {
const schema = [
{
enum: ['always', 'never'],
type: 'string'
}
];

const create = (context) => {
const sourceCode = context.getSourceCode();

const never = (context.options[0] || 'never') === 'never';
Expand Down Expand Up @@ -76,3 +83,8 @@ export default (context) => {
}
};
};

export default {
create,
schema
};
9 changes: 8 additions & 1 deletion src/rules/noDupeKeys.js
Expand Up @@ -3,7 +3,9 @@ import {
getParameterName
} from './../utilities';

export default (context) => {
const schema = [];

const create = (context) => {
const report = (node) => {
context.report({
loc: node.loc,
Expand Down Expand Up @@ -83,3 +85,8 @@ export default (context) => {
ObjectTypeAnnotation: checkForDuplicates
};
};

export default {
create,
schema
};
41 changes: 22 additions & 19 deletions src/rules/noPrimitiveConstructorTypes.js
@@ -1,24 +1,27 @@
import _ from 'lodash';

export default {
create: (context) => {
return {
GenericTypeAnnotation: (node) => {
const name = _.get(node, 'id.name');
const schema = [];

const create = (context) => {
return {
GenericTypeAnnotation: (node) => {
const name = _.get(node, 'id.name');

if (RegExp(/^(Boolean|Number|String)$/).test(name)) {
context.report({
data: {
name
},
loc: node.loc,
message: 'Unexpected use of {{name}} constructor type.',
node
});
}
if (RegExp(/^(Boolean|Number|String)$/).test(name)) {
context.report({
data: {
name
},
loc: node.loc,
message: 'Unexpected use of {{name}} constructor type.',
node
});
}
};
},
meta: {},
schema: {}
}
};
};

export default {
create,
schema
};
9 changes: 8 additions & 1 deletion src/rules/noTypesMissingFileAnnotation.js
Expand Up @@ -5,7 +5,9 @@ import {isFlowFile} from '../utilities';
* Only checks files without a valid flow annotation.
*/

export default (context) => {
const schema = [];

const create = (context) => {
// Skip flow files
if (isFlowFile(context, false)) {
return {};
Expand Down Expand Up @@ -42,3 +44,8 @@ export default (context) => {
}
};
};

export default {
create,
schema
};
25 changes: 24 additions & 1 deletion src/rules/noWeakTypes.js
@@ -1,5 +1,23 @@
import _ from 'lodash';

const schema = [
{
additionalProperties: false,
properties: {
Function: {
type: 'boolean'
},
Object: {
type: 'boolean'
},
any: {
type: 'boolean'
}
},
type: 'object'
}
];

const reportWeakType = (context, weakType) => {
return (node) => {
context.report({
Expand All @@ -20,7 +38,7 @@ const genericTypeEvaluator = (context, {checkFunction, checkObject}) => {
};
};

export default (context) => {
const create = (context) => {
const checkAny = _.get(context, 'options[0].any', true) === true;
const checkFunction = _.get(context, 'options[0].Function', true) === true;
const checkObject = _.get(context, 'options[0].Object', true) === true;
Expand All @@ -40,3 +58,8 @@ export default (context) => {

return checks;
};

export default {
create,
schema
};
3 changes: 2 additions & 1 deletion src/rules/objectTypeDelimiter.js
Expand Up @@ -49,7 +49,8 @@ const create = (context) => {

const schema = [
{
enum: ['semicolon', 'comma']
enum: ['semicolon', 'comma'],
type: 'string'
}
];

Expand Down
22 changes: 21 additions & 1 deletion src/rules/requireParameterType.js
Expand Up @@ -5,7 +5,22 @@ import {
quoteName
} from './../utilities';

export default iterateFunctionNodes((context) => {
const schema = [
{
additionalProperties: false,
properties: {
excludeArrowFunctions: {
enum: [false, true, 'expressionsOnly']
},
excludeParameterMatch: {
type: 'string'
}
},
type: 'object'
}
];

const create = iterateFunctionNodes((context) => {
const skipArrows = _.get(context, 'options[0].excludeArrowFunctions');
const excludeParameterMatch = new RegExp(_.get(context, 'options[0].excludeParameterMatch', 'a^'));

Expand Down Expand Up @@ -38,3 +53,8 @@ export default iterateFunctionNodes((context) => {
});
};
});

export default {
create,
schema
};
39 changes: 38 additions & 1 deletion src/rules/requireReturnType.js
@@ -1,6 +1,38 @@
import _ from 'lodash';

export default (context) => {
const schema = [
{
enum: ['always'],
type: 'string'
},
{
additionalProperties: false,
properties: {
annotateUndefined: {
enum: ['always', 'never'],
type: 'string'
},
excludeArrowFunctions: {
enum: [false, true, 'expressionsOnly']
},
excludeMatching: {
items: {
type: 'string'
},
type: 'array'
},
includeOnlyMatching: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}
];

const create = (context) => {
const annotateReturn = (_.get(context, 'options[0]') || 'always') === 'always';
const annotateUndefined = (_.get(context, 'options[1].annotateUndefined') || 'never') === 'always';
const skipArrows = _.get(context, 'options[1].excludeArrowFunctions') || false;
Expand Down Expand Up @@ -100,3 +132,8 @@ export default (context) => {
}
};
};

export default {
create,
schema
};

0 comments on commit b1409e3

Please sign in to comment.