From 42f2c1cc05337930e1b470d26788a6cd3c298324 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 2 Aug 2021 11:56:25 +1000 Subject: [PATCH 1/3] create rule and tests --- .README/README.md | 5 ++ .README/rules/interface-type-id-match.md | 22 +++++++ README.md | 59 +++++++++++++++-- src/index.js | 3 + src/rules/interfaceTypeIdMatch.js | 29 +++++++++ .../rules/assertions/interfaceTypeIdMatch.js | 63 +++++++++++++++++++ tests/rules/index.js | 1 + 7 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 .README/rules/interface-type-id-match.md create mode 100644 src/rules/interfaceTypeIdMatch.js create mode 100644 tests/rules/assertions/interfaceTypeIdMatch.js diff --git a/.README/README.md b/.README/README.md index 056df1a..7b0765f 100644 --- a/.README/README.md +++ b/.README/README.md @@ -54,6 +54,10 @@ npm install eslint babel-eslint eslint-plugin-flowtype --save-dev 2, "never" ], + "flowtype/interface-type-id-match": [ + 2, + "^([A-Z][a-z0-9]+)+Type$" + ], "flowtype/no-mixed": 2, "flowtype/no-primitive-constructor-types": 2, "flowtype/no-types-missing-file-annotation": 2, @@ -162,6 +166,7 @@ When `true`, only checks files with a [`@flow` annotation](http://flowtype.org/d {"gitdown": "include", "file": "./rules/delimiter-dangle.md"} {"gitdown": "include", "file": "./rules/enforce-line-break.md"} {"gitdown": "include", "file": "./rules/generic-spacing.md"} +{"gitdown": "include", "file": "./rules/interface-type-id-match.md"} {"gitdown": "include", "file": "./rules/newline-after-flow-annotation.md"} {"gitdown": "include", "file": "./rules/no-dupe-keys.md"} {"gitdown": "include", "file": "./rules/no-existential-type.md"} diff --git a/.README/rules/interface-type-id-match.md b/.README/rules/interface-type-id-match.md new file mode 100644 index 0000000..b8e6933 --- /dev/null +++ b/.README/rules/interface-type-id-match.md @@ -0,0 +1,22 @@ +### `interface-type-id-match` + +Enforces a consistent naming pattern for interfaces. + +#### Options + +This rule requires a text RegExp: + +```js +{ + "rules": { + "flowtype/interface-type-id-match": [ + 2, + "^([A-Z][a-z0-9]*)+Type$" + ] + } +} +``` + +`'^([A-Z][a-z0-9]*)+Type$$'` is the default pattern. + + diff --git a/README.md b/README.md index 6e6b24a..045f7a6 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ * [`delimiter-dangle`](#eslint-plugin-flowtype-rules-delimiter-dangle) * [`enforce-line-break`](#eslint-plugin-flowtype-rules-enforce-line-break) * [`generic-spacing`](#eslint-plugin-flowtype-rules-generic-spacing) + * [`interface-type-id-match`](#eslint-plugin-flowtype-rules-interface-type-id-match) * [`newline-after-flow-annotation`](#eslint-plugin-flowtype-rules-newline-after-flow-annotation) * [`no-dupe-keys`](#eslint-plugin-flowtype-rules-no-dupe-keys) * [`no-existential-type`](#eslint-plugin-flowtype-rules-no-existential-type) @@ -109,6 +110,10 @@ npm install eslint babel-eslint eslint-plugin-flowtype --save-dev 2, "never" ], + "flowtype/interface-type-id-match": [ + 2, + "^([A-Z][a-z0-9]+)+Type$" + ], "flowtype/no-mixed": 2, "flowtype/no-primitive-constructor-types": 2, "flowtype/no-types-missing-file-annotation": 2, @@ -1829,7 +1834,53 @@ type X = Promise< (string) > type X = Promise< (foo), bar, (((baz))) > ``` + +### interface-type-id-match + +Enforces a consistent naming pattern for interfaces. + + +#### Options + + +This rule requires a text RegExp: + +```js +{ + "rules": { + "flowtype/interface-type-id-match": [ + 2, + "^([A-Z][a-z0-9]*)+Type$" + ] + } +} +``` + +`'^([A-Z][a-z0-9]*)+Type$$'` is the default pattern. +The following patterns are considered problems: + +```js + +interface foo{}; +// Message: Type identifier 'foo' does not match pattern '/^([A-Z][a-z0-9]*)+Type$/'. + +// Options: ["^foo$"] +interface FooType{}; +// Message: Type identifier 'FooType' does not match pattern '/^foo$/'. +``` + +The following patterns are not considered problems: + +```js +interface FooType{}; + +// Options: ["^foo$"] +interface foo {}; + +// Settings: {"flowtype":{"onlyFilesWithFlowAnnotation":true}} +interface foo {}; +``` ### newline-after-flow-annotation @@ -1870,7 +1921,7 @@ import Foo from './foo'; // Message: Expected newline after flow annotation // Options: ["always-windows"] -// @flow +// @flow import Foo from './foo'; // Message: Expected newline after flow annotation @@ -1890,8 +1941,8 @@ The following patterns are not considered problems: import Foo from './foo'; // Options: ["always-windows"] -// @flow - +// @flow + import Foo from './foo'; // Options: ["never"] @@ -5392,7 +5443,7 @@ The following patterns are not considered problems: { a: string, b: number }) => {} // Options: ["always",{"allowLineBreak":true}] -(foo: +(foo: { a: string, b: number }) => {} // Options: ["never"] diff --git a/src/index.js b/src/index.js index 04b2973..07b6d33 100644 --- a/src/index.js +++ b/src/index.js @@ -8,6 +8,7 @@ import defineFlowType from './rules/defineFlowType'; import delimiterDangle from './rules/delimiterDangle'; import enforceLineBreak from './rules/enforceLineBreak'; import genericSpacing from './rules/genericSpacing'; +import interfaceTypeIdMatch from './rules/interfaceTypeIdMatch'; import newlineAfterFlowAnnotation from './rules/newlineAfterFlowAnnotation'; import noDupeKeys from './rules/noDupeKeys'; import noExistentialType from './rules/noExistentialType'; @@ -56,6 +57,7 @@ const rules = { 'delimiter-dangle': delimiterDangle, 'enforce-line-break': enforceLineBreak, 'generic-spacing': genericSpacing, + 'interface-type-id-match': interfaceTypeIdMatch, 'newline-after-flow-annotation': newlineAfterFlowAnnotation, 'no-dupe-keys': noDupeKeys, 'no-existential-type': noExistentialType, @@ -113,6 +115,7 @@ export default { 'define-flow-type': 0, 'delimiter-dangle': 0, 'generic-spacing': 0, + 'interface-type-id-match': 0, 'newline-after-flow-annotation': 0, 'no-dupe-keys': 0, 'no-flow-fix-me-comments': 0, diff --git a/src/rules/interfaceTypeIdMatch.js b/src/rules/interfaceTypeIdMatch.js new file mode 100644 index 0000000..d358449 --- /dev/null +++ b/src/rules/interfaceTypeIdMatch.js @@ -0,0 +1,29 @@ +const schema = [ + { + type: 'string', + }, +]; + +const create = (context) => { + const pattern = new RegExp(context.options[0] || '^([A-Z][a-z0-9]*)+Type$'); + + const checkType = (interfaceDeclarationNode) => { + const typeIdentifierName = interfaceDeclarationNode.id.name; + + if (!pattern.test(typeIdentifierName)) { + context.report(interfaceDeclarationNode, 'Type identifier \'{{name}}\' does not match pattern \'{{pattern}}\'.', { + name: typeIdentifierName, + pattern: pattern.toString(), + }); + } + }; + + return { + InterfaceDeclaration: checkType, + }; +}; + +export default { + create, + schema, +}; diff --git a/tests/rules/assertions/interfaceTypeIdMatch.js b/tests/rules/assertions/interfaceTypeIdMatch.js new file mode 100644 index 0000000..b7e5b18 --- /dev/null +++ b/tests/rules/assertions/interfaceTypeIdMatch.js @@ -0,0 +1,63 @@ +export default { + invalid: [ + { + code: 'interface foo{};', + errors: [ + { + message: 'Type identifier \'foo\' does not match pattern \'/^([A-Z][a-z0-9]*)+Type$/\'.', + }, + ], + }, + { + code: 'interface FooType{};', + errors: [ + { + message: 'Type identifier \'FooType\' does not match pattern \'/^foo$/\'.', + }, + ], + options: [ + '^foo$', + ], + }, + ], + misconfigured: [ + { + errors: [ + { + data: 7, + dataPath: '[0]', + keyword: 'type', + message: 'should be string', + params: { + type: 'string', + }, + parentSchema: { + type: 'string', + }, + schema: 'string', + schemaPath: '#/items/0/type', + }, + ], + options: [7], + }, + ], + valid: [ + { + code: 'interface FooType {};', + }, + { + code: 'interface foo {};', + options: [ + '^foo$', + ], + }, + { + code: 'interface foo {};', + settings: { + flowtype: { + onlyFilesWithFlowAnnotation: true, + }, + }, + }, + ], +}; diff --git a/tests/rules/index.js b/tests/rules/index.js index 7fddff4..9242ae6 100644 --- a/tests/rules/index.js +++ b/tests/rules/index.js @@ -19,6 +19,7 @@ const reportingRules = [ 'delimiter-dangle', 'enforce-line-break', 'generic-spacing', + 'interface-type-id-match', 'newline-after-flow-annotation', 'no-dupe-keys', 'no-existential-type', From a01566557ccc6e2da6ff9f65f82e89c910b1f87c Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 2 Aug 2021 12:10:18 +1000 Subject: [PATCH 2/3] reset readme --- README.md | 54 +----------------------------------------------------- 1 file changed, 1 insertion(+), 53 deletions(-) diff --git a/README.md b/README.md index 045f7a6..468beba 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,6 @@ * [`delimiter-dangle`](#eslint-plugin-flowtype-rules-delimiter-dangle) * [`enforce-line-break`](#eslint-plugin-flowtype-rules-enforce-line-break) * [`generic-spacing`](#eslint-plugin-flowtype-rules-generic-spacing) - * [`interface-type-id-match`](#eslint-plugin-flowtype-rules-interface-type-id-match) * [`newline-after-flow-annotation`](#eslint-plugin-flowtype-rules-newline-after-flow-annotation) * [`no-dupe-keys`](#eslint-plugin-flowtype-rules-no-dupe-keys) * [`no-existential-type`](#eslint-plugin-flowtype-rules-no-existential-type) @@ -110,10 +109,6 @@ npm install eslint babel-eslint eslint-plugin-flowtype --save-dev 2, "never" ], - "flowtype/interface-type-id-match": [ - 2, - "^([A-Z][a-z0-9]+)+Type$" - ], "flowtype/no-mixed": 2, "flowtype/no-primitive-constructor-types": 2, "flowtype/no-types-missing-file-annotation": 2, @@ -1834,53 +1829,7 @@ type X = Promise< (string) > type X = Promise< (foo), bar, (((baz))) > ``` - -### interface-type-id-match - -Enforces a consistent naming pattern for interfaces. - - -#### Options - - -This rule requires a text RegExp: - -```js -{ - "rules": { - "flowtype/interface-type-id-match": [ - 2, - "^([A-Z][a-z0-9]*)+Type$" - ] - } -} -``` - -`'^([A-Z][a-z0-9]*)+Type$$'` is the default pattern. - -The following patterns are considered problems: - -```js - -interface foo{}; -// Message: Type identifier 'foo' does not match pattern '/^([A-Z][a-z0-9]*)+Type$/'. - -// Options: ["^foo$"] -interface FooType{}; -// Message: Type identifier 'FooType' does not match pattern '/^foo$/'. -``` - -The following patterns are not considered problems: - -```js -interface FooType{}; -// Options: ["^foo$"] -interface foo {}; - -// Settings: {"flowtype":{"onlyFilesWithFlowAnnotation":true}} -interface foo {}; -``` ### newline-after-flow-annotation @@ -3079,7 +3028,7 @@ The rule has two options: } ``` -* `allowNull` – allows compound types where one of the members is a `null`, e.g. `string | null`. +* `allowNull` – allows compound types where one of the members is a `null`, e.g. `string | null`. The following patterns are considered problems: @@ -6770,4 +6719,3 @@ function x(foo: Type = bar()) {} ``` - From fe75195ee6565a1f0ddb0e09430690236fd45d4a Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 2 Aug 2021 13:09:14 +1000 Subject: [PATCH 3/3] update naming conventions --- .README/README.md | 4 +-- ...type-id-match.md => interface-id-match.md} | 6 ++-- src/index.js | 6 ++-- src/rules/interfaceIdMatch.js | 29 +++++++++++++++++++ src/rules/interfaceTypeIdMatch.js | 29 ------------------- ...faceTypeIdMatch.js => interfaceIdMatch.js} | 4 +-- tests/rules/index.js | 2 +- 7 files changed, 40 insertions(+), 40 deletions(-) rename .README/rules/{interface-type-id-match.md => interface-id-match.md} (68%) create mode 100644 src/rules/interfaceIdMatch.js delete mode 100644 src/rules/interfaceTypeIdMatch.js rename tests/rules/assertions/{interfaceTypeIdMatch.js => interfaceIdMatch.js} (83%) diff --git a/.README/README.md b/.README/README.md index 7b0765f..be062c4 100644 --- a/.README/README.md +++ b/.README/README.md @@ -54,7 +54,7 @@ npm install eslint babel-eslint eslint-plugin-flowtype --save-dev 2, "never" ], - "flowtype/interface-type-id-match": [ + "flowtype/interface-id-match": [ 2, "^([A-Z][a-z0-9]+)+Type$" ], @@ -166,7 +166,7 @@ When `true`, only checks files with a [`@flow` annotation](http://flowtype.org/d {"gitdown": "include", "file": "./rules/delimiter-dangle.md"} {"gitdown": "include", "file": "./rules/enforce-line-break.md"} {"gitdown": "include", "file": "./rules/generic-spacing.md"} -{"gitdown": "include", "file": "./rules/interface-type-id-match.md"} +{"gitdown": "include", "file": "./rules/interface-id-match.md"} {"gitdown": "include", "file": "./rules/newline-after-flow-annotation.md"} {"gitdown": "include", "file": "./rules/no-dupe-keys.md"} {"gitdown": "include", "file": "./rules/no-existential-type.md"} diff --git a/.README/rules/interface-type-id-match.md b/.README/rules/interface-id-match.md similarity index 68% rename from .README/rules/interface-type-id-match.md rename to .README/rules/interface-id-match.md index b8e6933..39fdc90 100644 --- a/.README/rules/interface-type-id-match.md +++ b/.README/rules/interface-id-match.md @@ -1,4 +1,4 @@ -### `interface-type-id-match` +### `interface-id-match` Enforces a consistent naming pattern for interfaces. @@ -9,7 +9,7 @@ This rule requires a text RegExp: ```js { "rules": { - "flowtype/interface-type-id-match": [ + "flowtype/interface-id-match": [ 2, "^([A-Z][a-z0-9]*)+Type$" ] @@ -19,4 +19,4 @@ This rule requires a text RegExp: `'^([A-Z][a-z0-9]*)+Type$$'` is the default pattern. - + diff --git a/src/index.js b/src/index.js index 07b6d33..66bc783 100644 --- a/src/index.js +++ b/src/index.js @@ -8,7 +8,7 @@ import defineFlowType from './rules/defineFlowType'; import delimiterDangle from './rules/delimiterDangle'; import enforceLineBreak from './rules/enforceLineBreak'; import genericSpacing from './rules/genericSpacing'; -import interfaceTypeIdMatch from './rules/interfaceTypeIdMatch'; +import interfaceIdMatch from './rules/interfaceIdMatch'; import newlineAfterFlowAnnotation from './rules/newlineAfterFlowAnnotation'; import noDupeKeys from './rules/noDupeKeys'; import noExistentialType from './rules/noExistentialType'; @@ -57,7 +57,7 @@ const rules = { 'delimiter-dangle': delimiterDangle, 'enforce-line-break': enforceLineBreak, 'generic-spacing': genericSpacing, - 'interface-type-id-match': interfaceTypeIdMatch, + 'interface-id-match': interfaceIdMatch, 'newline-after-flow-annotation': newlineAfterFlowAnnotation, 'no-dupe-keys': noDupeKeys, 'no-existential-type': noExistentialType, @@ -115,7 +115,7 @@ export default { 'define-flow-type': 0, 'delimiter-dangle': 0, 'generic-spacing': 0, - 'interface-type-id-match': 0, + 'interface-id-match': 0, 'newline-after-flow-annotation': 0, 'no-dupe-keys': 0, 'no-flow-fix-me-comments': 0, diff --git a/src/rules/interfaceIdMatch.js b/src/rules/interfaceIdMatch.js new file mode 100644 index 0000000..47b689f --- /dev/null +++ b/src/rules/interfaceIdMatch.js @@ -0,0 +1,29 @@ +const schema = [ + { + type: 'string', + }, +]; + +const create = (context) => { + const pattern = new RegExp(context.options[0] || '^([A-Z][a-z0-9]*)+Type$'); + + const checkInterface = (interfaceDeclarationNode) => { + const interfaceIdentifierName = interfaceDeclarationNode.id.name; + + if (!pattern.test(interfaceIdentifierName)) { + context.report(interfaceDeclarationNode, 'Interface identifier \'{{name}}\' does not match pattern \'{{pattern}}\'.', { + name: interfaceIdentifierName, + pattern: pattern.toString(), + }); + } + }; + + return { + InterfaceDeclaration: checkInterface, + }; +}; + +export default { + create, + schema, +}; diff --git a/src/rules/interfaceTypeIdMatch.js b/src/rules/interfaceTypeIdMatch.js deleted file mode 100644 index d358449..0000000 --- a/src/rules/interfaceTypeIdMatch.js +++ /dev/null @@ -1,29 +0,0 @@ -const schema = [ - { - type: 'string', - }, -]; - -const create = (context) => { - const pattern = new RegExp(context.options[0] || '^([A-Z][a-z0-9]*)+Type$'); - - const checkType = (interfaceDeclarationNode) => { - const typeIdentifierName = interfaceDeclarationNode.id.name; - - if (!pattern.test(typeIdentifierName)) { - context.report(interfaceDeclarationNode, 'Type identifier \'{{name}}\' does not match pattern \'{{pattern}}\'.', { - name: typeIdentifierName, - pattern: pattern.toString(), - }); - } - }; - - return { - InterfaceDeclaration: checkType, - }; -}; - -export default { - create, - schema, -}; diff --git a/tests/rules/assertions/interfaceTypeIdMatch.js b/tests/rules/assertions/interfaceIdMatch.js similarity index 83% rename from tests/rules/assertions/interfaceTypeIdMatch.js rename to tests/rules/assertions/interfaceIdMatch.js index b7e5b18..f160111 100644 --- a/tests/rules/assertions/interfaceTypeIdMatch.js +++ b/tests/rules/assertions/interfaceIdMatch.js @@ -4,7 +4,7 @@ export default { code: 'interface foo{};', errors: [ { - message: 'Type identifier \'foo\' does not match pattern \'/^([A-Z][a-z0-9]*)+Type$/\'.', + message: 'Interface identifier \'foo\' does not match pattern \'/^([A-Z][a-z0-9]*)+Type$/\'.', }, ], }, @@ -12,7 +12,7 @@ export default { code: 'interface FooType{};', errors: [ { - message: 'Type identifier \'FooType\' does not match pattern \'/^foo$/\'.', + message: 'Interface identifier \'FooType\' does not match pattern \'/^foo$/\'.', }, ], options: [ diff --git a/tests/rules/index.js b/tests/rules/index.js index 9242ae6..619b6a0 100644 --- a/tests/rules/index.js +++ b/tests/rules/index.js @@ -19,7 +19,7 @@ const reportingRules = [ 'delimiter-dangle', 'enforce-line-break', 'generic-spacing', - 'interface-type-id-match', + 'interface-id-match', 'newline-after-flow-annotation', 'no-dupe-keys', 'no-existential-type',