[Pkg-javascript-commits] [node-eslint-plugin-flowtype] 01/02: Import Upstream version 2.25.0

Thorsten Alteholz alteholz at moszumanska.debian.org
Tue Sep 19 20:25:03 UTC 2017


This is an automated email from the git hooks/post-receive script.

alteholz pushed a commit to branch master
in repository node-eslint-plugin-flowtype.

commit 482efd00e434a776641bdd63a952814a594c2ae0
Author: Thorsten Alteholz <debian at alteholz.de>
Date:   Tue Sep 19 22:24:53 2017 +0200

    Import Upstream version 2.25.0
---
 .README/README.md                                  |  161 +
 .README/rules/boolean-style.md                     |   13 +
 .README/rules/define-flow-type.md                  |    7 +
 .README/rules/delimiter-dangle.md                  |   19 +
 .README/rules/generic-spacing.md                   |   11 +
 .README/rules/no-dupe-keys.md                      |   15 +
 .README/rules/no-weak-types.md                     |   33 +
 .README/rules/object-type-delimiter.md             |   17 +
 .README/rules/require-parameter-type.md            |   53 +
 .README/rules/require-return-type.md               |   37 +
 .README/rules/require-valid-file-annotation.md     |   43 +
 .README/rules/semi.md                              |   11 +
 .README/rules/sort-keys.md                         |   33 +
 .README/rules/space-after-type-colon.md            |    9 +
 .README/rules/space-before-generic-bracket.md      |   11 +
 .README/rules/space-before-type-colon.md           |    9 +
 .README/rules/type-id-match.md                     |   22 +
 .README/rules/union-intersection-spacing.md        |   11 +
 .README/rules/use-flow-type.md                     |    7 +
 .README/rules/valid-syntax.md                      |    5 +
 .babelrc                                           |    9 +
 .eslintrc                                          |    3 +
 .gitignore                                         |   12 +
 .npmignore                                         |    5 +
 .scripts/release.sh                                |   61 +
 .travis.yml                                        |   18 +
 CHANGELOG.md                                       |  268 ++
 CONTRIBUTING.md                                    |   52 +
 LICENSE                                            |   24 +
 README.md                                          | 3249 ++++++++++++++++++++
 bin/readmeAssertions.js                            |   84 +
 package.json                                       |   57 +
 src/configs/recommended.json                       |   44 +
 src/index.js                                       |   67 +
 src/rules/booleanStyle.js                          |   29 +
 src/rules/defineFlowType.js                        |   64 +
 src/rules/delimiterDangle.js                       |  105 +
 src/rules/genericSpacing.js                        |   78 +
 src/rules/noDupeKeys.js                            |   32 +
 src/rules/noWeakTypes.js                           |   42 +
 src/rules/objectTypeDelimiter.js                   |   59 +
 src/rules/requireParameterType.js                  |   47 +
 src/rules/requireReturnType.js                     |   83 +
 src/rules/requireValidFileAnnotation.js            |   66 +
 src/rules/semi.js                                  |   52 +
 src/rules/sortKeys.js                              |   91 +
 src/rules/spaceAfterTypeColon.js                   |    7 +
 src/rules/spaceBeforeGenericBracket.js             |   47 +
 src/rules/spaceBeforeTypeColon.js                  |    7 +
 src/rules/typeColonSpacing/evaluateFunctions.js    |   14 +
 .../typeColonSpacing/evaluateObjectTypeIndexer.js  |   21 +
 .../typeColonSpacing/evaluateObjectTypeProperty.js |   42 +
 src/rules/typeColonSpacing/evaluateReturnType.js   |   16 +
 .../typeColonSpacing/evaluateTypeCastExpression.js |   11 +
 src/rules/typeColonSpacing/evaluateTypical.js      |   27 +
 src/rules/typeColonSpacing/index.js                |   18 +
 src/rules/typeColonSpacing/reporter.js             |   45 +
 src/rules/typeIdMatch.js                           |   22 +
 src/rules/unionIntersectionSpacing.js              |   67 +
 src/rules/useFlowType.js                           |   36 +
 src/rules/validSyntax.js                           |   27 +
 src/utilities/getParameterName.js                  |   52 +
 src/utilities/getTokenAfterParens.js               |   13 +
 src/utilities/getTokenBeforeParens.js              |   13 +
 src/utilities/index.js                             |   10 +
 src/utilities/isFlowFile.js                        |   13 +
 src/utilities/isFlowFileAnnotation.js              |   13 +
 src/utilities/iterateFunctionNodes.js              |   12 +
 src/utilities/quoteName.js                         |    3 +
 src/utilities/spacingFixers.js                     |   39 +
 tests/rules/assertions/booleanStyle.js             |   34 +
 tests/rules/assertions/defineFlowType.js           |  219 ++
 tests/rules/assertions/delimiterDangle.js          |  512 +++
 tests/rules/assertions/genericSpacing.js           |  117 +
 tests/rules/assertions/noDupeKeys.js               |   17 +
 tests/rules/assertions/noWeakTypes.js              |  251 ++
 tests/rules/assertions/objectTypeDelimiter.js      |  147 +
 tests/rules/assertions/requireParameterType.js     |  195 ++
 tests/rules/assertions/requireReturnType.js        |  476 +++
 .../rules/assertions/requireValidFileAnnotation.js |  146 +
 tests/rules/assertions/semi.js                     |   55 +
 tests/rules/assertions/sortKeys.js                 |   84 +
 tests/rules/assertions/spaceAfterTypeColon.js      | 1014 ++++++
 .../rules/assertions/spaceBeforeGenericBracket.js  |   41 +
 tests/rules/assertions/spaceBeforeTypeColon.js     |  845 +++++
 tests/rules/assertions/typeIdMatch.js              |   34 +
 tests/rules/assertions/unionIntersectionSpacing.js |  202 ++
 tests/rules/assertions/useFlowType.js              |  190 ++
 tests/rules/assertions/validSyntax.js              |   13 +
 tests/rules/index.js                               |   51 +
 90 files changed, 10446 insertions(+)

diff --git a/.README/README.md b/.README/README.md
new file mode 100644
index 0000000..a63c691
--- /dev/null
+++ b/.README/README.md
@@ -0,0 +1,161 @@
+# eslint-plugin-flowtype
+
+[![NPM version](http://img.shields.io/npm/v/eslint-plugin-flowtype.svg?style=flat-square)](https://www.npmjs.org/package/eslint-plugin-flowtype)
+[![Travis build status](http://img.shields.io/travis/gajus/eslint-plugin-flowtype/master.svg?style=flat-square)](https://travis-ci.org/gajus/eslint-plugin-flowtype)
+[![js-canonical-style](https://img.shields.io/badge/code%20style-canonical-blue.svg?style=flat-square)](https://github.com/gajus/canonical)
+
+[Flow type](http://flowtype.org/) linting rules for ESLint.
+
+{"gitdown": "contents"}
+
+## Installation
+
+1. Install [ESLint](https://www.github.com/eslint/eslint).
+1. Install [`babel-eslint`](https://github.com/babel/babel-eslint) parser (ESLint parser [does not support type annotations](https://github.com/eslint/eslint/issues/2157)).
+1. Install [`eslint-plugin-flowtype`](https://github.com/gajus/eslint-plugin-flowtype) plugin.
+
+<!-- -->
+
+```sh
+npm install eslint
+npm install babel-eslint
+npm install eslint-plugin-flowtype
+```
+
+## Configuration
+
+1. Set `parser` property to `babel-eslint`.
+1. Add `plugins` section and specify `eslint-plugin-flowtype` as a plugin.
+1. Enable rules.
+
+<!-- -->
+
+```json
+{
+  "parser": "babel-eslint",
+  "plugins": [
+    "flowtype"
+  ],
+  "rules": {
+    "flowtype/boolean-style": [
+      2,
+      "boolean"
+    ],
+    "flowtype/define-flow-type": 1,
+    "flowtype/delimiter-dangle": [
+      2,
+      "never"
+    ],
+    "flowtype/generic-spacing": [
+      2,
+      "never"
+    ],
+    "flowtype/no-weak-types": 2,
+    "flowtype/object-type-delimiter": [
+      2,
+      "comma"
+    ],
+    "flowtype/require-parameter-type": 2,
+    "flowtype/require-return-type": [
+      2,
+      "always",
+      {
+        "annotateUndefined": "never"
+      }
+    ],
+    "flowtype/require-valid-file-annotation": 2,
+    "flowtype/semi": [
+      2,
+      "always"
+    ],
+    "flowtype/space-after-type-colon": [
+      2,
+      "always"
+    ],
+    "flowtype/space-before-generic-bracket": [
+      2,
+      "never"
+    ],
+    "flowtype/space-before-type-colon": [
+      2,
+      "never"
+    ],
+    "flowtype/type-id-match": [
+      2,
+      "^([A-Z][a-z0-9]+)+Type$"
+    ],
+    "flowtype/union-intersection-spacing": [
+      2,
+      "always"
+    ],
+    "flowtype/use-flow-type": 1,
+    "flowtype/valid-syntax": 1
+  },
+  "settings": {
+    "flowtype": {
+      "onlyFilesWithFlowAnnotation": false
+    }
+  }
+}
+```
+
+### Shareable configurations
+
+#### Recommended
+
+This plugin exports a [recommended configuration](./src/configs/recommended.json) that enforces Flow type good practices.
+
+To enable this configuration use the extends property in your `.eslintrc` config file:
+
+```json
+{
+  "extends": [
+    "plugin:flowtype/recommended"
+  ],
+  "plugins": [
+    "flowtype"
+  ]
+}
+```
+
+See [ESLint documentation](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) for more information about extending configuration files.
+
+## Settings
+
+### `onlyFilesWithFlowAnnotation`
+
+When `true`, only checks files with a [`@flow` annotation](http://flowtype.org/docs/about-flow.html#gradual) in the first comment.
+
+```js
+{
+  "settings": {
+    "flowtype": {
+      "onlyFilesWithFlowAnnotation": true
+    }
+  }
+}
+```
+
+## Rules
+
+<!-- Rules are sorted alphabetically. -->
+
+{"gitdown": "include", "file": "./rules/boolean-style.md"}
+{"gitdown": "include", "file": "./rules/define-flow-type.md"}
+{"gitdown": "include", "file": "./rules/delimiter-dangle.md"}
+{"gitdown": "include", "file": "./rules/generic-spacing.md"}
+{"gitdown": "include", "file": "./rules/no-dupe-keys.md"}
+{"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-return-type.md"}
+{"gitdown": "include", "file": "./rules/require-valid-file-annotation.md"}
+{"gitdown": "include", "file": "./rules/semi.md"}
+{"gitdown": "include", "file": "./rules/sort-keys.md"}
+{"gitdown": "include", "file": "./rules/space-after-type-colon.md"}
+{"gitdown": "include", "file": "./rules/space-before-generic-bracket.md"}
+{"gitdown": "include", "file": "./rules/space-before-type-colon.md"}
+{"gitdown": "include", "file": "./rules/type-id-match.md"}
+{"gitdown": "include", "file": "./rules/union-intersection-spacing.md"}
+{"gitdown": "include", "file": "./rules/use-flow-type.md"}
+{"gitdown": "include", "file": "./rules/valid-syntax.md"}
diff --git a/.README/rules/boolean-style.md b/.README/rules/boolean-style.md
new file mode 100644
index 0000000..7637a23
--- /dev/null
+++ b/.README/rules/boolean-style.md
@@ -0,0 +1,13 @@
+### `boolean-style`
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces a particular style for boolean type annotations. This rule takes one argument.
+
+If it is `'boolean'` then a problem is raised when using `bool` instead of `boolean`.
+
+If it is `'bool'` then a problem is raised when using `boolean` instead of `bool`.
+
+The default value is `'boolean'`.
+
+<!-- assertions booleanStyle -->
diff --git a/.README/rules/define-flow-type.md b/.README/rules/define-flow-type.md
new file mode 100644
index 0000000..d103645
--- /dev/null
+++ b/.README/rules/define-flow-type.md
@@ -0,0 +1,7 @@
+### `define-flow-type`
+
+Marks Flow type identifiers as defined.
+
+Used to suppress [`no-undef`](http://eslint.org/docs/rules/no-undef) reporting of type identifiers.
+
+<!-- assertions defineFlowType -->
diff --git a/.README/rules/delimiter-dangle.md b/.README/rules/delimiter-dangle.md
new file mode 100644
index 0000000..46eb144
--- /dev/null
+++ b/.README/rules/delimiter-dangle.md
@@ -0,0 +1,19 @@
+### `delimiter-dangle`
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent use of trailing commas in Object and Tuple annotations.
+
+This rule takes one argument which mirrors ESLint's default `comma-dangle` rule.
+
+If it is `'never'` then a problem is raised when there is a trailing comma.
+
+If it is `'always'` then a problem is raised when there is no trailing comma.
+
+If it is `'always-multiline'` then a problem is raised when there is no trailing comma on a multi-line definition, or there _is_ a trailing comma on a single-line definition.
+
+If it is `'only-multiline'` then a problem is raised when there is a trailing comma on a single-line definition. It allows, but does not enforce, trailing commas on multi-line definitions.
+
+The default value is `'never'`.
+
+<!-- assertions delimiterDangle -->
diff --git a/.README/rules/generic-spacing.md b/.README/rules/generic-spacing.md
new file mode 100644
index 0000000..7254e48
--- /dev/null
+++ b/.README/rules/generic-spacing.md
@@ -0,0 +1,11 @@
+### `generic-spacing`
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent spacing within generic type annotation parameters.
+
+This rule takes one argument. If it is `'never'` then a problem is raised when there is a space surrounding the generic type parameters. If it is `'always'` then a problem is raised when there is no space surrounding the generic type parameters.
+
+The default value is `'never'`.
+
+<!-- assertions genericSpacing -->
diff --git a/.README/rules/no-dupe-keys.md b/.README/rules/no-dupe-keys.md
new file mode 100644
index 0000000..447ecba
--- /dev/null
+++ b/.README/rules/no-dupe-keys.md
@@ -0,0 +1,15 @@
+### `no-dupe-keys`
+
+Checks for duplicate properties in Object annotations.
+
+This rule mirrors ESLint's [no-dupe-keys](http://eslint.org/docs/rules/no-dupe-keys) rule.
+
+```js
+{
+    "rules": {
+        "flowtype/no-dupe-keys": 2
+    }
+}
+```
+
+<!-- assertions noDupeKeys -->
diff --git a/.README/rules/no-weak-types.md b/.README/rules/no-weak-types.md
new file mode 100644
index 0000000..5005840
--- /dev/null
+++ b/.README/rules/no-weak-types.md
@@ -0,0 +1,33 @@
+### `no-weak-types`
+
+Warns against weak type annotations *any*, *Object* and *Function*.
+These types can cause flow to silently skip over portions of your code,
+which would have otherwise caused type errors.
+
+This rule optionally takes one argument, an object to configure which type warnings to enable. By default, all of the
+warnings are enabled. e.g. to disable the `any` warning (allowing it to exist in your code), while continuing to warn
+about `Object` and `Function`:
+
+```js
+{
+    "rules": {
+        "flowtype/no-weak-types": [2, {
+            "any": false,
+            "Object": true,
+            "Function": true
+        }]
+    }
+}
+
+// or, the following is equivalent as default is true:
+
+{
+    "rules": {
+        "flowtype/no-weak-types": [2, {
+            "any": false
+        }]
+    }
+}
+```
+
+<!-- assertions noWeakTypes -->
diff --git a/.README/rules/object-type-delimiter.md b/.README/rules/object-type-delimiter.md
new file mode 100644
index 0000000..41c1706
--- /dev/null
+++ b/.README/rules/object-type-delimiter.md
@@ -0,0 +1,17 @@
+### `object-type-delimiter`
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent separators between properties in Flow object types.
+
+This rule takes one argument.
+
+If it is `'comma'` then a problem is raised when using `;` as a separator.
+
+If it is `'semicolon'` then a problem is raised when using `,` as a separator.
+
+The default value is `'comma'`.
+
+_This rule is ported from `babel/flow-object-type`, however the default option was changed._
+
+<!-- assertions objectTypeDelimiter -->
diff --git a/.README/rules/require-parameter-type.md b/.README/rules/require-parameter-type.md
new file mode 100644
index 0000000..83bc065
--- /dev/null
+++ b/.README/rules/require-parameter-type.md
@@ -0,0 +1,53 @@
+### `require-parameter-type`
+
+Requires that all function parameters have type annotations.
+
+#### Options
+
+You can skip all arrow functions by providing the `excludeArrowFunctions` option with `true`.
+
+Alternatively, you can want to exclude only concise arrow functions (e.g. `x => x * 2`). Provide `excludeArrowFunctions` with `expressionsOnly` for this.
+
+```js
+{
+    "rules": {
+        "flowtype/require-parameter-type": [
+            2,
+            {
+              "excludeArrowFunctions": true
+            }
+        ]
+    }
+}
+
+{
+    "rules": {
+        "flowtype/require-parameter-type": [
+            2,
+            {
+              "excludeArrowFunctions": "expressionsOnly"
+            }
+        ]
+    }
+}
+```
+
+You can exclude parameters that match a certain regex by using `excludeParameterMatch`.
+
+```js
+{
+    "rules": {
+        "flowtype/require-parameter-type": [
+            2,
+            {
+              "excludeParameterMatch": "^_"
+            }
+        ]
+    }
+}
+```
+
+This excludes all parameters that start with an underscore (`_`).
+The default pattern is `a^`, which doesn't match anything, i.e., all parameters are checked.
+
+<!-- assertions requireParameterType -->
diff --git a/.README/rules/require-return-type.md b/.README/rules/require-return-type.md
new file mode 100644
index 0000000..371a723
--- /dev/null
+++ b/.README/rules/require-return-type.md
@@ -0,0 +1,37 @@
+### `require-return-type`
+
+Requires that functions have return type annotation.
+
+#### Options
+
+You can skip all arrow functions by providing the `excludeArrowFunctions` option with `true`.
+
+Alternatively, you can want to exclude only concise arrow function (e.g. `() => 2`). Provide `excludeArrowFunctions` with `expressionsOnly` for this.
+
+```js
+{
+    "rules": {
+        "flowtype/require-return-type": [
+            2,
+            "always",
+            {
+              "excludeArrowFunctions": true
+            }
+        ]
+    }
+}
+
+{
+    "rules": {
+        "flowtype/require-return-type": [
+            2,
+            "always",
+            {
+              "excludeArrowFunctions": "expressionsOnly"
+            }
+        ]
+    }
+}
+```
+
+<!-- assertions requireReturnType -->
diff --git a/.README/rules/require-valid-file-annotation.md b/.README/rules/require-valid-file-annotation.md
new file mode 100644
index 0000000..02b973f
--- /dev/null
+++ b/.README/rules/require-valid-file-annotation.md
@@ -0,0 +1,43 @@
+### `require-valid-file-annotation`
+
+This rule validates Flow file annotations.
+
+This rule can optionally report missing or missed placed annotations, common typos (e.g. `// @floww`), and enforce a consistant annotation style.
+
+#### Options
+
+The rule has a string option:
+
+* `"never"` (default): Never report files that are missing an `@flow` annotation.
+* `"always"`: Always report files that are missing an `@flow` annotation
+
+This rule has an object option:
+
+* `"annotationStyle"` - Enforce a consistant file annotation style.
+    * `"none"` (default): Either annotation style is accepted.
+    * `"line"`: Require single line annotations (i.e. `// @flow`).
+    * `"block"`: Require block annotations (i.e. `/* @flow */`).
+
+```js
+{
+  "rules": {
+    "flowtype/require-valid-file-annotation": [
+      2,
+      "always"
+    ]
+  }
+}
+
+{
+  "rules": {
+    "flowtype/require-valid-file-annotation": [
+      2,
+      "always", {
+        "annotationStyle": "block"
+      }
+    ]
+  }
+}
+```
+
+<!-- assertions requireValidFileAnnotation -->
diff --git a/.README/rules/semi.md b/.README/rules/semi.md
new file mode 100644
index 0000000..1b6cae1
--- /dev/null
+++ b/.README/rules/semi.md
@@ -0,0 +1,11 @@
+### `semi`
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent use of semicolons after type aliases.
+
+This rule takes one argument. If it is `'never'` then a problem is raised when there is a semicolon after a type alias. If it is `'always'` then a problem is raised when there is no semicolon after a type alias.
+
+The default value is `'always'`.
+
+<!-- assertions semi -->
diff --git a/.README/rules/sort-keys.md b/.README/rules/sort-keys.md
new file mode 100644
index 0000000..a083bb6
--- /dev/null
+++ b/.README/rules/sort-keys.md
@@ -0,0 +1,33 @@
+### `sort-keys`
+
+Enforces sorting of Object annotations.
+
+This rule mirrors ESlint's [sort-keys](http://eslint.org/docs/rules/sort-keys) rule.
+
+#### Options
+
+The first option specifies sort order.
+
+* `"asc"` (default) - enforce ascending sort order.
+* `"desc"` - enforce descending sort order.
+
+The second option takes an object with two possible properties.
+
+* `caseSensitive` - if `true`, enforce case-sensitive sort order. Default is `true`.
+* `natural` - if `true`, enforce [natural sort order](https://en.wikipedia.org/wiki/Natural_sort_order). Default is `false`.
+
+```js
+{
+  "rules": {
+    "flowtype/sort-keys": [
+      2,
+      "asc", {
+        "caseSensitive": true,
+        "natural": false
+      }
+    ]
+  }
+}
+```
+
+<!-- assertions sortKeys -->
diff --git a/.README/rules/space-after-type-colon.md b/.README/rules/space-after-type-colon.md
new file mode 100644
index 0000000..5b54edc
--- /dev/null
+++ b/.README/rules/space-after-type-colon.md
@@ -0,0 +1,9 @@
+### `space-after-type-colon`
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent spacing after the type annotation colon.
+
+This rule takes one argument. If it is `'always'` then a problem is raised when there is no space after the type annotation colon. If it is `'never'` then a problem is raised when there is a space after the type annotation colon. The default value is `'always'`.
+
+<!-- assertions spaceAfterTypeColon -->
diff --git a/.README/rules/space-before-generic-bracket.md b/.README/rules/space-before-generic-bracket.md
new file mode 100644
index 0000000..305966a
--- /dev/null
+++ b/.README/rules/space-before-generic-bracket.md
@@ -0,0 +1,11 @@
+### `space-before-generic-bracket`
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent spacing before the opening `<` of generic type annotation parameters.
+
+This rule takes one argument. If it is `'never'` then a problem is raised when there is a space before the `<`. If it is `'always'` then a problem is raised when there is no space before the `<`.
+
+The default value is `'never'`.
+
+<!-- assertions spaceBeforeGenericBracket -->
diff --git a/.README/rules/space-before-type-colon.md b/.README/rules/space-before-type-colon.md
new file mode 100644
index 0000000..1643ae0
--- /dev/null
+++ b/.README/rules/space-before-type-colon.md
@@ -0,0 +1,9 @@
+### `space-before-type-colon`
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent spacing before the type annotation colon.
+
+This rule takes one argument. If it is `'always'` then a problem is raised when there is no space before the type annotation colon. If it is `'never'` then a problem is raised when there is a space before the type annotation colon. The default value is `'never'`.
+
+<!-- assertions spaceBeforeTypeColon -->
diff --git a/.README/rules/type-id-match.md b/.README/rules/type-id-match.md
new file mode 100644
index 0000000..6fe9302
--- /dev/null
+++ b/.README/rules/type-id-match.md
@@ -0,0 +1,22 @@
+### `type-id-match`
+
+Enforces a consistent naming pattern for type aliases.
+
+#### Options
+
+This rule needs a text RegExp to operate with Its signature is as follows:
+
+```js
+{
+    "rules": {
+        "flowtype/type-id-match": [
+            2,
+            "^([A-Z][a-z0-9]*)+Type$"
+        ]
+    }
+}
+```
+
+`'^([A-Z][a-z0-9]*)+Type$$'` is the default pattern.
+
+<!-- assertions typeIdMatch -->
diff --git a/.README/rules/union-intersection-spacing.md b/.README/rules/union-intersection-spacing.md
new file mode 100644
index 0000000..a0e6cb3
--- /dev/null
+++ b/.README/rules/union-intersection-spacing.md
@@ -0,0 +1,11 @@
+### `union-intersection-spacing`
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent spacing around union and intersection type separators (`|` and `&`).
+
+This rule takes one argument. If it is `'always'` then a problem is raised when there is no space around the separator. If it is `'never'` then a problem is raised when there is a space around the separator.
+
+The default value is `'always'`.
+
+<!-- assertions unionIntersectionSpacing -->
diff --git a/.README/rules/use-flow-type.md b/.README/rules/use-flow-type.md
new file mode 100644
index 0000000..35f77c7
--- /dev/null
+++ b/.README/rules/use-flow-type.md
@@ -0,0 +1,7 @@
+### `use-flow-type`
+
+Marks Flow [type alias](https://flowtype.org/docs/type-aliases.html) declarations as used.
+
+Used to suppress [`no-unused-vars`](http://eslint.org/docs/rules/no-unused-vars) errors that are triggered by type aliases.
+
+<!-- assertions useFlowType -->
diff --git a/.README/rules/valid-syntax.md b/.README/rules/valid-syntax.md
new file mode 100644
index 0000000..a0126e2
--- /dev/null
+++ b/.README/rules/valid-syntax.md
@@ -0,0 +1,5 @@
+### `valid-syntax`
+
+**Deprecated** Babylon (the Babel parser) v6.10.0 fixes parsing of the invalid syntax this plugin warned against.
+
+Checks for simple Flow syntax errors.
diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..d43233e
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,9 @@
+{
+    "presets": [
+        "es2015",
+        "stage-0"
+    ],
+    "plugins": [
+        "add-module-exports"
+    ]
+}
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..40288f8
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,3 @@
+{
+    "extends": "canonical"
+}
diff --git a/.gitignore b/.gitignore
new file mode 100755
index 0000000..5364199
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+node_modules
+coverage
+dist
+*.log
+.*
+!.eslintrc
+!.gitignore
+!.npmignore
+!.babelrc
+!.travis.yml
+!.README
+!.scripts
diff --git a/.npmignore b/.npmignore
new file mode 100755
index 0000000..e8add85
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,5 @@
+src
+tests
+coverage
+.*
+*.log
diff --git a/.scripts/release.sh b/.scripts/release.sh
new file mode 100755
index 0000000..68eb40f
--- /dev/null
+++ b/.scripts/release.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+set -ex
+
+if [[ $TRAVIS_PULL_REQUEST != "false" ]]; then
+  echo 'This is a pull request. Exiting the release script.'
+
+  exit 0
+fi
+
+if [[ -n $TRAVIS_TAG ]]; then
+  echo 'This is a tag release.'
+
+  # Use NPM_TOKEN to enable NPM authentication
+  set +x
+  echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
+  set -x
+
+  NODE_ENV=development npm install
+  NODE_ENV=production npm run build
+
+  npm publish
+  exit 0
+fi
+
+if [[ $TRAVIS_BRANCH != "master" ]]; then
+  echo 'This is not a master branch. Exiting the release script.'
+
+  exit 0
+fi
+
+if [[ $(git log --format=%B -n 1 $TRAVIS_COMMIT) == *"chore: release"* ]]; then
+  echo 'This is a tag release. Exiting the release script.'
+
+  exit 0
+fi;
+
+git config --global user.name 'continuous-deployment'
+git config --global user.email 'continuous-deployment at travis'
+
+# Use GITHUB_TOKEN to enable GitHub authentication
+git config credential.helper "store --file=.git/credentials"
+set +x
+echo "https://${GITHUB_TOKEN}:@github.com" > .git/credentials
+set -x
+
+git checkout master
+git merge $TRAVIS_COMMIT
+
+# Generate ./README.md from ./.README/README.md template.
+npm run documentation
+
+git add ./README.md
+git diff-index --quiet HEAD ./README.md || git commit --no-verify -m 'docs: update documentation' ./README.md
+
+# 1. bump the package.json version (based on your commit history)
+# 2. update CHANGELOG.md
+# 3. commit package.json and CHANGELOG.md
+# 4. tag the release
+standard-version --no-verify --message "chore: release %s"
+
+git push --follow-tags origin master
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..7570750
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,18 @@
+language: node_js
+node_js:
+  - 6
+  - 5
+  - 4
+before_install:
+  - npm config set depth 0
+  - npm install --global npm at 3
+notifications:
+  email: false
+sudo: false
+script:
+  - npm run test
+  - npm run lint
+  - npm run build
+  - conventional-changelog-lint --from=HEAD~$(git --no-pager rev-list master..HEAD --count)
+after_success:
+  - travis-after-all && ./.scripts/release.sh
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..31f4b8e
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,268 @@
+# Change Log
+
+All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+
+<a name="2.25.0"></a>
+# [2.25.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.24.0...v2.25.0) (2016-10-25)
+
+
+### Features
+
+* Add excludeParameterMatch option to require-parameter-type ([d9cfbbe](https://github.com/gajus/eslint-plugin-flowtype/commit/d9cfbbe))
+
+
+
+<a name="2.24.0"></a>
+# [2.24.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.23.1...v2.24.0) (2016-10-25)
+
+
+### Features
+
+* add additional tests for function return types ([795b3a4](https://github.com/gajus/eslint-plugin-flowtype/commit/795b3a4))
+
+
+
+<a name="2.23.1"></a>
+## [2.23.1](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.23.0...v2.23.1) (2016-10-25)
+
+
+### Bug Fixes
+
+* Support more properties in object-type-delimiter ([6b0a677](https://github.com/gajus/eslint-plugin-flowtype/commit/6b0a677))
+
+
+
+<a name="2.23.0"></a>
+# [2.23.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.22.0...v2.23.0) (2016-10-24)
+
+
+### Features
+
+* add object-type-delimiter rule ([a99721b](https://github.com/gajus/eslint-plugin-flowtype/commit/a99721b))
+
+
+
+<a name="2.22.0"></a>
+# [2.22.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.21.0...v2.22.0) (2016-10-24)
+
+
+### Features
+
+* ObjectTypeIndexer in spaceBeforeTypeColon & spaceAfterTypeColon ([82c87c4](https://github.com/gajus/eslint-plugin-flowtype/commit/82c87c4)), closes [#134](https://github.com/gajus/eslint-plugin-flowtype/issues/134)
+
+
+
+<a name="2.21.0"></a>
+# [2.21.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.20.0...v2.21.0) (2016-10-22)
+
+
+### Features
+
+* Add variance support to spaceBeforeTypeColon & spaceAfterTypeColon ([4a7f87f](https://github.com/gajus/eslint-plugin-flowtype/commit/4a7f87f)), closes [#137](https://github.com/gajus/eslint-plugin-flowtype/issues/137)
+
+
+
+<a name="2.20.0"></a>
+# [2.20.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.19.0...v2.20.0) (2016-10-06)
+
+
+### Features
+
+* add annotation enforcement option ([dd71ce8](https://github.com/gajus/eslint-plugin-flowtype/commit/dd71ce8))
+
+
+
+<a name="2.19.0"></a>
+# [2.19.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.18.2...v2.19.0) (2016-09-20)
+
+
+### Bug Fixes
+
+* parens in TypeCastExpression ([0e0081f](https://github.com/gajus/eslint-plugin-flowtype/commit/0e0081f))
+
+### Features
+
+* add rule `sort-keys` (fixes #104) ([f6b8deb](https://github.com/gajus/eslint-plugin-flowtype/commit/f6b8deb)), closes [#104](https://github.com/gajus/eslint-plugin-flowtype/issues/104)
+* check TypeCastExpressions in type colon spacing rules ([98839f0](https://github.com/gajus/eslint-plugin-flowtype/commit/98839f0))
+
+
+
+<a name="2.18.2"></a>
+## [2.18.2](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.18.1...v2.18.2) (2016-09-18)
+
+
+
+
+<a name="2.18.1"></a>
+## [2.18.1](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.18.0...v2.18.1) (2016-09-15)
+
+
+
+
+<a name="2.18.0"></a>
+# [2.18.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.17.1...v2.18.0) (2016-09-15)
+
+
+### Features
+
+* add rule `no-dupe-keys` (fixes #108) (#109) ([6a65de0](https://github.com/gajus/eslint-plugin-flowtype/commit/6a65de0)), closes [#108](https://github.com/gajus/eslint-plugin-flowtype/issues/108) [(#109](https://github.com/(/issues/109)
+
+
+
+<a name="2.17.1"></a>
+## [2.17.1](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.17.0...v2.17.1) (2016-09-12)
+
+
+### Bug Fixes
+
+* config file (json failing lint) ([eedcac7](https://github.com/gajus/eslint-plugin-flowtype/commit/eedcac7))
+* correct recommended config name ([35150d4](https://github.com/gajus/eslint-plugin-flowtype/commit/35150d4))
+* disable lint for one run ([3745498](https://github.com/gajus/eslint-plugin-flowtype/commit/3745498))
+
+
+
+<a name="2.17.0"></a>
+# [2.17.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.16.1...v2.17.0) (2016-09-12)
+
+
+### Features
+
+* define recommended configuration ([dc2e35b](https://github.com/gajus/eslint-plugin-flowtype/commit/dc2e35b))
+* export recommended configuration ([f7d7a21](https://github.com/gajus/eslint-plugin-flowtype/commit/f7d7a21))
+
+
+
+<a name="2.16.1"></a>
+## [2.16.1](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.16.0...v2.16.1) (2016-09-09)
+
+
+
+
+<a name="2.16.0"></a>
+# [2.16.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.15.0...v2.16.0) (2016-09-07)
+
+
+### Bug Fixes
+
+* `delimiter-dangle` with indexers ([9ff6f37](https://github.com/gajus/eslint-plugin-flowtype/commit/9ff6f37))
+* reported locations in `delimiter-dangle` ([06fbd92](https://github.com/gajus/eslint-plugin-flowtype/commit/06fbd92))
+
+### Features
+
+* add `delimiter-dangle` for trailing commas/semicolons ([788f480](https://github.com/gajus/eslint-plugin-flowtype/commit/788f480))
+
+
+
+<a name="2.15.0"></a>
+# [2.15.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.14.3...v2.15.0) (2016-09-05)
+
+
+### Features
+
+* options to prevent specific types in `no-weak-types` (#99) ([9c903ad](https://github.com/gajus/eslint-plugin-flowtype/commit/9c903ad))
+
+
+
+<a name="2.14.3"></a>
+## [2.14.3](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.14.2...v2.14.3) (2016-09-05)
+
+
+### Bug Fixes
+
+* ensure not to print private tokens ([1e41818](https://github.com/gajus/eslint-plugin-flowtype/commit/1e41818))
+
+
+
+<a name="2.14.2"></a>
+## [2.14.2](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.14.1...v2.14.2) (2016-09-05)
+
+
+### Bug Fixes
+
+* move tag check prior to branch check ([29b35d0](https://github.com/gajus/eslint-plugin-flowtype/commit/29b35d0))
+
+
+
+<a name="2.14.1"></a>
+## [2.14.1](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.14.0...v2.14.1) (2016-09-05)
+
+
+### Bug Fixes
+
+* add a condition to prevent empty commit ([2e6ddfa](https://github.com/gajus/eslint-plugin-flowtype/commit/2e6ddfa))
+* fix release script ([260b86b](https://github.com/gajus/eslint-plugin-flowtype/commit/260b86b))
+
+
+
+<a name="2.14.0"></a>
+# [2.14.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.13.0...v2.14.0) (2016-09-05)
+
+
+### Features
+
+* add new rule `no-weak-types` (#96) ([c1a94c5](https://github.com/gajus/eslint-plugin-flowtype/commit/c1a94c5))
+
+
+
+<a name="2.13.0"></a>
+# [2.13.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.12.1...v2.13.0) (2016-09-03)
+
+
+### Features
+
+* add new rule `boolean-style` (#98) ([1ab7902](https://github.com/gajus/eslint-plugin-flowtype/commit/1ab7902))
+
+
+
+<a name="2.12.1"></a>
+## [2.12.1](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.12.0...v2.12.1) (2016-09-01)
+
+
+### Bug Fixes
+
+* allow uppercase sequences in 'type-id-match' (#93) ([000b0d1](https://github.com/gajus/eslint-plugin-flowtype/commit/000b0d1))
+
+
+
+<a name="2.12.0"></a>
+# [2.12.0](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.11.5...v2.12.0) (2016-09-01)
+
+
+### Bug Fixes
+
+* add --no-verify to docs commit ([393643b](https://github.com/gajus/eslint-plugin-flowtype/commit/393643b))
+* add --no-verify to standard-version ([22a0559](https://github.com/gajus/eslint-plugin-flowtype/commit/22a0559))
+
+### Features
+
+* add new rule "semi" for semicolon linting (#95) ([ead974d](https://github.com/gajus/eslint-plugin-flowtype/commit/ead974d))
+
+
+
+<a name="2.11.5"></a>
+## [2.11.5](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.11.4...v2.11.5) (2016-09-01)
+
+
+
+<a name="2.11.4"></a>
+## [2.11.4](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.11.3...v2.11.4) (2016-08-23)
+
+
+
+<a name="2.11.3"></a>
+## [2.11.3](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.11.2...v2.11.3) (2016-08-23)
+
+
+### Bug Fixes
+
+* commit documentation changes ([15a8289](https://github.com/gajus/eslint-plugin-flowtype/commit/15a8289))
+
+
+
+<a name="2.11.2"></a>
+## [2.11.2](https://github.com/gajus/eslint-plugin-flowtype/compare/v2.11.1...v2.11.2) (2016-08-23)
+
+
+### Bug Fixes
+
+* make release.sh executable ([6fa6f89](https://github.com/gajus/eslint-plugin-flowtype/commit/6fa6f89))
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..6a39e87
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,52 @@
+# Contributing
+
+**`README.md` is a generated file. Do not edit it directly.** Edit the files inside `.README` instead.
+
+## Pre-Commit Hook
+
+When making a commit, the following Pre-Commit hooks run:
+
+* tests
+* lint
+* commit message validation (see "Commit Messages" below)
+
+## Commit Messages
+
+All commit messages must begin with one of the following prefixes:
+
+* `fix: `
+* `feat: `
+* `refactor: `
+* `docs: `
+* `chore: `
+
+The prefix is used to bump the correct segment of the version number automatically during deploy.
+
+## Tests
+
+Run them with `npm t`.
+
+## Lint
+
+Run with `npm run lint`.
+
+## Adding a Rule
+
+### Source & Tests
+
+1. Create a file in `tests/rules/assertions` named the `camelCase` version of your rule name with the following template:
+  * `export default { invalid: [], valid: [] }`
+2. Add your test file to `tests/index.js`
+3. Create a file in `src/rules` named the `camelCase` version  of your rule name
+4. Add your rule file to `src/index.js`
+
+### Adding Documentation
+
+1. Create new file in `./README/rules/[rule-name].md`.
+  * Use [./.README/rules/require-valid-file-annotation.md](./.README/rules/require-valid-file-annotation.md) as a template.
+  * Ensure that rule documentation document includes `<!-- assertions spaceAfterTypeColon -->` declaration.
+1. Update [./.README/README.md](/.README/README.md) to include the new rule.
+
+A CI service will build and publish the new documentation.
+
+Note: The section "The following patterns are considered problems:" and "The following patterns are not considered problems:" is **generated automatically** using the test cases.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..183e8d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2015, Gajus Kuizinas (http://gajus.com/)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Gajus Kuizinas (http://gajus.com/) nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL ANUARY BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..937937b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3249 @@
+<a name="eslint-plugin-flowtype"></a>
+# eslint-plugin-flowtype
+
+[![NPM version](http://img.shields.io/npm/v/eslint-plugin-flowtype.svg?style=flat-square)](https://www.npmjs.org/package/eslint-plugin-flowtype)
+[![Travis build status](http://img.shields.io/travis/gajus/eslint-plugin-flowtype/master.svg?style=flat-square)](https://travis-ci.org/gajus/eslint-plugin-flowtype)
+[![js-canonical-style](https://img.shields.io/badge/code%20style-canonical-blue.svg?style=flat-square)](https://github.com/gajus/canonical)
+
+[Flow type](http://flowtype.org/) linting rules for ESLint.
+
+* [eslint-plugin-flowtype](#eslint-plugin-flowtype)
+    * [Installation](#eslint-plugin-flowtype-installation)
+    * [Configuration](#eslint-plugin-flowtype-configuration)
+        * [Shareable configurations](#eslint-plugin-flowtype-configuration-shareable-configurations)
+    * [Settings](#eslint-plugin-flowtype-settings)
+        * [`onlyFilesWithFlowAnnotation`](#eslint-plugin-flowtype-settings-onlyfileswithflowannotation)
+    * [Rules](#eslint-plugin-flowtype-rules)
+        * [`boolean-style`](#eslint-plugin-flowtype-rules-boolean-style)
+        * [`define-flow-type`](#eslint-plugin-flowtype-rules-define-flow-type)
+        * [`delimiter-dangle`](#eslint-plugin-flowtype-rules-delimiter-dangle)
+        * [`generic-spacing`](#eslint-plugin-flowtype-rules-generic-spacing)
+        * [`no-dupe-keys`](#eslint-plugin-flowtype-rules-no-dupe-keys)
+        * [`no-weak-types`](#eslint-plugin-flowtype-rules-no-weak-types)
+        * [`object-type-delimiter`](#eslint-plugin-flowtype-rules-object-type-delimiter)
+        * [`require-parameter-type`](#eslint-plugin-flowtype-rules-require-parameter-type)
+        * [`require-return-type`](#eslint-plugin-flowtype-rules-require-return-type)
+        * [`require-valid-file-annotation`](#eslint-plugin-flowtype-rules-require-valid-file-annotation)
+        * [`semi`](#eslint-plugin-flowtype-rules-semi)
+        * [`sort-keys`](#eslint-plugin-flowtype-rules-sort-keys)
+        * [`space-after-type-colon`](#eslint-plugin-flowtype-rules-space-after-type-colon)
+        * [`space-before-generic-bracket`](#eslint-plugin-flowtype-rules-space-before-generic-bracket)
+        * [`space-before-type-colon`](#eslint-plugin-flowtype-rules-space-before-type-colon)
+        * [`type-id-match`](#eslint-plugin-flowtype-rules-type-id-match)
+        * [`union-intersection-spacing`](#eslint-plugin-flowtype-rules-union-intersection-spacing)
+        * [`use-flow-type`](#eslint-plugin-flowtype-rules-use-flow-type)
+        * [`valid-syntax`](#eslint-plugin-flowtype-rules-valid-syntax)
+
+
+<a name="eslint-plugin-flowtype-installation"></a>
+## Installation
+
+1. Install [ESLint](https://www.github.com/eslint/eslint).
+1. Install [`babel-eslint`](https://github.com/babel/babel-eslint) parser (ESLint parser [does not support type annotations](https://github.com/eslint/eslint/issues/2157)).
+1. Install [`eslint-plugin-flowtype`](https://github.com/gajus/eslint-plugin-flowtype) plugin.
+
+<!-- -->
+
+```sh
+npm install eslint
+npm install babel-eslint
+npm install eslint-plugin-flowtype
+```
+
+<a name="eslint-plugin-flowtype-configuration"></a>
+## Configuration
+
+1. Set `parser` property to `babel-eslint`.
+1. Add `plugins` section and specify `eslint-plugin-flowtype` as a plugin.
+1. Enable rules.
+
+<!-- -->
+
+```json
+{
+  "parser": "babel-eslint",
+  "plugins": [
+    "flowtype"
+  ],
+  "rules": {
+    "flowtype/boolean-style": [
+      2,
+      "boolean"
+    ],
+    "flowtype/define-flow-type": 1,
+    "flowtype/delimiter-dangle": [
+      2,
+      "never"
+    ],
+    "flowtype/generic-spacing": [
+      2,
+      "never"
+    ],
+    "flowtype/no-weak-types": 2,
+    "flowtype/object-type-delimiter": [
+      2,
+      "comma"
+    ],
+    "flowtype/require-parameter-type": 2,
+    "flowtype/require-return-type": [
+      2,
+      "always",
+      {
+        "annotateUndefined": "never"
+      }
+    ],
+    "flowtype/require-valid-file-annotation": 2,
+    "flowtype/semi": [
+      2,
+      "always"
+    ],
+    "flowtype/space-after-type-colon": [
+      2,
+      "always"
+    ],
+    "flowtype/space-before-generic-bracket": [
+      2,
+      "never"
+    ],
+    "flowtype/space-before-type-colon": [
+      2,
+      "never"
+    ],
+    "flowtype/type-id-match": [
+      2,
+      "^([A-Z][a-z0-9]+)+Type$"
+    ],
+    "flowtype/union-intersection-spacing": [
+      2,
+      "always"
+    ],
+    "flowtype/use-flow-type": 1,
+    "flowtype/valid-syntax": 1
+  },
+  "settings": {
+    "flowtype": {
+      "onlyFilesWithFlowAnnotation": false
+    }
+  }
+}
+```
+
+<a name="eslint-plugin-flowtype-configuration-shareable-configurations"></a>
+### Shareable configurations
+
+<a name="eslint-plugin-flowtype-configuration-shareable-configurations-recommended"></a>
+#### Recommended
+
+This plugin exports a [recommended configuration](./src/configs/recommended.json) that enforces Flow type good practices.
+
+To enable this configuration use the extends property in your `.eslintrc` config file:
+
+```json
+{
+  "extends": [
+    "plugin:flowtype/recommended"
+  ],
+  "plugins": [
+    "flowtype"
+  ]
+}
+```
+
+See [ESLint documentation](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) for more information about extending configuration files.
+
+<a name="eslint-plugin-flowtype-settings"></a>
+## Settings
+
+<a name="eslint-plugin-flowtype-settings-onlyfileswithflowannotation"></a>
+### <code>onlyFilesWithFlowAnnotation</code>
+
+When `true`, only checks files with a [`@flow` annotation](http://flowtype.org/docs/about-flow.html#gradual) in the first comment.
+
+```js
+{
+  "settings": {
+    "flowtype": {
+      "onlyFilesWithFlowAnnotation": true
+    }
+  }
+}
+```
+
+<a name="eslint-plugin-flowtype-rules"></a>
+## Rules
+
+<!-- Rules are sorted alphabetically. -->
+
+<a name="eslint-plugin-flowtype-rules-boolean-style"></a>
+### <code>boolean-style</code>
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces a particular style for boolean type annotations. This rule takes one argument.
+
+If it is `'boolean'` then a problem is raised when using `bool` instead of `boolean`.
+
+If it is `'bool'` then a problem is raised when using `boolean` instead of `bool`.
+
+The default value is `'boolean'`.
+
+The following patterns are considered problems:
+
+```js
+type X = bool
+// Message: Use "boolean", not "bool"
+
+// Options: ["boolean"]
+type X = bool
+// Message: Use "boolean", not "bool"
+
+// Options: ["bool"]
+type X = boolean
+// Message: Use "bool", not "boolean"
+```
+
+The following patterns are not considered problems:
+
+```js
+type X = boolean
+
+// Options: ["boolean"]
+type X = boolean
+
+// Options: ["bool"]
+type X = bool
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-define-flow-type"></a>
+### <code>define-flow-type</code>
+
+Marks Flow type identifiers as defined.
+
+Used to suppress [`no-undef`](http://eslint.org/docs/rules/no-undef) reporting of type identifiers.
+
+The following patterns are not considered problems:
+
+```js
+var a: AType
+// Additional rules: {"no-undef":2}
+
+var a: AType; var b: AType
+// Additional rules: {"no-undef":2}
+
+var a; (a: AType)
+// Additional rules: {"no-undef":2}
+
+var a: AType<BType>
+// Additional rules: {"no-undef":2}
+
+type A = AType
+// Additional rules: {"no-undef":2}
+
+function f(a: AType) {}
+// Additional rules: {"no-undef":2}
+
+function f(a: AType.a) {}
+// Additional rules: {"no-undef":2}
+
+function f(a: AType.a.b) {}
+// Additional rules: {"no-undef":2}
+
+function f(a): AType {}; var a: AType
+// Additional rules: {"no-undef":2}
+
+function f(a): AType {}
+// Additional rules: {"no-undef":2}
+
+class C { a: AType }
+// Additional rules: {"no-undef":2}
+
+class C { a: AType.a }
+// Additional rules: {"no-undef":2}
+
+class C { a: AType.a.b }
+// Additional rules: {"no-undef":2}
+
+class C implements AType {}
+// Additional rules: {"no-undef":2}
+
+interface AType {}
+// Additional rules: {"no-undef":2}
+
+({ a: ({b() {}}: AType) })
+// Additional rules: {"no-undef":2}
+
+type X = {Y<AType>(): BType}
+// Additional rules: {"no-undef":2}
+
+interface AType<BType> {}
+// Additional rules: {"no-undef":2}
+
+var a: AType
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+var a: AType; var b: AType
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+var a; (a: AType)
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+var a: AType<BType>
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+type A = AType
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+function f(a: AType) {}
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+function f(a: AType.a) {}
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+function f(a: AType.a.b) {}
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+function f(a): AType {}; var a: AType
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+function f(a): AType {}
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+class C { a: AType }
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+class C { a: AType.a }
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+class C { a: AType.a.b }
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+class C implements AType {}
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+interface AType {}
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+({ a: ({b() {}}: AType) })
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+type X = {Y<AType>(): BType}
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+
+interface AType<BType> {}
+// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-delimiter-dangle"></a>
+### <code>delimiter-dangle</code>
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent use of trailing commas in Object and Tuple annotations.
+
+This rule takes one argument which mirrors ESLint's default `comma-dangle` rule.
+
+If it is `'never'` then a problem is raised when there is a trailing comma.
+
+If it is `'always'` then a problem is raised when there is no trailing comma.
+
+If it is `'always-multiline'` then a problem is raised when there is no trailing comma on a multi-line definition, or there _is_ a trailing comma on a single-line definition.
+
+If it is `'only-multiline'` then a problem is raised when there is a trailing comma on a single-line definition. It allows, but does not enforce, trailing commas on multi-line definitions.
+
+The default value is `'never'`.
+
+The following patterns are considered problems:
+
+```js
+type X = { foo: string, }
+// Message: Unexpected trailing delimiter
+
+// Options: ["never"]
+type X = { foo: string, }
+// Message: Unexpected trailing delimiter
+
+// Options: ["never"]
+type X = { foo: string; }
+// Message: Unexpected trailing delimiter
+
+// Options: ["never"]
+type X = {
+foo: string,
+}
+// Message: Unexpected trailing delimiter
+
+// Options: ["always"]
+type X = { foo: string }
+// Message: Missing trailing delimiter
+
+// Options: ["always"]
+type X = {
+foo: string
+}
+// Message: Missing trailing delimiter
+
+// Options: ["always-multiline"]
+type X = { foo: string, }
+// Message: Unexpected trailing delimiter
+
+// Options: ["always-multiline"]
+type X = {
+foo: string
+}
+// Message: Missing trailing delimiter
+
+// Options: ["only-multiline"]
+type X = { foo: string; }
+// Message: Unexpected trailing delimiter
+
+// Options: ["never"]
+type X = { [key: string]: number, }
+// Message: Unexpected trailing delimiter
+
+// Options: ["always"]
+type X = { [key: string]: number }
+// Message: Missing trailing delimiter
+
+// Options: ["always-multiline"]
+type X = { [key: string]: number, }
+// Message: Unexpected trailing delimiter
+
+// Options: ["always-multiline"]
+type X = {
+[key: string]: number
+}
+// Message: Missing trailing delimiter
+
+// Options: ["only-multiline"]
+type X = { [key: string]: number; }
+// Message: Unexpected trailing delimiter
+
+// Options: ["never"]
+type X = { [key: string]: number, foo: string, }
+// Message: Unexpected trailing delimiter
+
+// Options: ["never"]
+type X = {
+[key: string]: number,
+foo: string,
+}
+// Message: Unexpected trailing delimiter
+
+// Options: ["never"]
+type X = {
+[key: string]: number,
+aReallyLongPropertyNameHere: string,
+}
+// Message: Unexpected trailing delimiter
+
+// Options: ["always"]
+type X = { [key: string]: number, foo: string }
+// Message: Missing trailing delimiter
+
+// Options: ["always"]
+type X = {
+[key: string]: number;
+foo: string
+}
+// Message: Missing trailing delimiter
+
+// Options: ["always-multiline"]
+type X = { [key: string]: number, foo: string, }
+// Message: Unexpected trailing delimiter
+
+// Options: ["always-multiline"]
+type X = {
+[key: string]: number,
+foo: string
+}
+// Message: Missing trailing delimiter
+
+// Options: ["only-multiline"]
+type X = { [key: string]: number, foo: string, }
+// Message: Unexpected trailing delimiter
+
+// Options: ["never"]
+type X = { foo: string, [key: string]: number, }
+// Message: Unexpected trailing delimiter
+
+// Options: ["never"]
+type X = {
+foo: string,
+[key: string]: number,
+}
+// Message: Unexpected trailing delimiter
+
+// Options: ["never"]
+type X = {
+aReallyLongPropertyNameHere: string,
+[key: string]: number,
+}
+// Message: Unexpected trailing delimiter
+
+// Options: ["always"]
+type X = { foo: string, [key: string]: number }
+// Message: Missing trailing delimiter
+
+// Options: ["always"]
+type X = { foo: string; [key: string]: number }
+// Message: Missing trailing delimiter
+
+// Options: ["always-multiline"]
+type X = { foo: string, [key: string]: number; }
+// Message: Unexpected trailing delimiter
+
+// Options: ["always-multiline"]
+type X = {
+foo: string,
+[key: string]: number
+}
+// Message: Missing trailing delimiter
+
+// Options: ["only-multiline"]
+type X = { foo: string, [key: string]: number; }
+// Message: Unexpected trailing delimiter
+
+type X = [string, number,]
+// Message: Unexpected trailing delimiter
+
+// Options: ["never"]
+type X = [string, number,]
+// Message: Unexpected trailing delimiter
+
+// Options: ["never"]
+type X = [
+string,
+number,
+]
+// Message: Unexpected trailing delimiter
+
+// Options: ["always"]
+type X = [string, number]
+// Message: Missing trailing delimiter
+
+// Options: ["always"]
+type X = [
+string,
+number
+]
+// Message: Missing trailing delimiter
+
+// Options: ["always-multiline"]
+type X = [string, number,]
+// Message: Unexpected trailing delimiter
+
+// Options: ["always-multiline"]
+type X = [
+foo, string
+]
+// Message: Missing trailing delimiter
+
+// Options: ["only-multiline"]
+type X = [ number, string, ]
+// Message: Unexpected trailing delimiter
+```
+
+The following patterns are not considered problems:
+
+```js
+type X = { foo: string }
+
+// Options: ["never"]
+type X = { foo: string }
+
+// Options: ["always"]
+type X = { foo: string, }
+
+// Options: ["always"]
+type X = { foo: string; }
+
+// Options: ["never"]
+type X = {
+foo: string
+}
+
+// Options: ["always"]
+type X = {
+foo: string,
+}
+
+// Options: ["always-multiline"]
+type X = { foo: string }
+
+// Options: ["always-multiline"]
+type X = {
+foo: string,
+}
+
+// Options: ["always-multiline"]
+type X = {
+foo: string;
+}
+
+// Options: ["only-multiline"]
+type X = { foo: string }
+
+// Options: ["only-multiline"]
+type X = {
+foo: string
+}
+
+// Options: ["only-multiline"]
+type X = {
+foo: string,
+}
+
+// Options: ["only-multiline"]
+type X = {
+foo: string;
+}
+
+// Options: ["never"]
+type X = {}
+
+// Options: ["always"]
+type X = {}
+
+// Options: ["always-multiline"]
+type X = {}
+
+// Options: ["only-multiline"]
+type X = {}
+
+// Options: ["never"]
+type X = { [key: string]: number }
+
+// Options: ["always"]
+type X = { [key: string]: number, }
+
+// Options: ["always"]
+type X = { [key: string]: number; }
+
+// Options: ["always-multiline"]
+type X = { [key: string]: number }
+
+// Options: ["always-multiline"]
+type X = {
+[key: string]: number,
+}
+
+// Options: ["only-multiline"]
+type X = {
+[key: string]: number,
+}
+
+// Options: ["only-multiline"]
+type X = {
+[key: string]: number
+}
+
+// Options: ["only-multiline"]
+type X = { [key: string]: number }
+
+// Options: ["never"]
+type X = { [key: string]: number, foo: string }
+
+// Options: ["always"]
+type X = { [key: string]: number, foo: string, }
+
+// Options: ["always"]
+type X = { [key: string]: number; foo: string; }
+
+// Options: ["always-multiline"]
+type X = { [key: string]: number, foo: string }
+
+// Options: ["always-multiline"]
+type X = {
+[key: string]: number,
+foo: string,
+}
+
+// Options: ["only-multiline"]
+type X = {
+[key: string]: number,
+foo: string,
+}
+
+// Options: ["only-multiline"]
+type X = {
+[key: string]: number;
+foo: string
+}
+
+// Options: ["only-multiline"]
+type X = { [key: string]: number, foo: string }
+
+// Options: ["never"]
+type X = { foo: string, [key: string]: number }
+
+// Options: ["always"]
+type X = { foo: string, [key: string]: number, }
+
+// Options: ["always"]
+type X = { foo: string; [key: string]: number; }
+
+// Options: ["always-multiline"]
+type X = { foo: string, [key: string]: number }
+
+// Options: ["always-multiline"]
+type X = {
+foo: string,
+[key: string]: number,
+}
+
+// Options: ["only-multiline"]
+type X = {
+foo: string,
+[key: string]: number,
+}
+
+// Options: ["only-multiline"]
+type X = {
+foo: string;
+[key: string]: number
+}
+
+// Options: ["only-multiline"]
+type X = { foo: string, [key: string]: number }
+
+type X = [string, number]
+
+// Options: ["never"]
+type X = [string, number]
+
+// Options: ["never"]
+type X = [
+string,
+number
+]
+
+// Options: ["always"]
+type X = [string, number,]
+
+// Options: ["always"]
+type X = [
+string,
+number,
+]
+
+// Options: ["always-multiline"]
+type X = [ foo, string ]
+
+// Options: ["always-multiline"]
+type X = [
+foo, string,
+]
+
+// Options: ["only-multiline"]
+type X = [ number, string ]
+
+// Options: ["only-multiline"]
+type X = [
+number,
+string
+]
+
+// Options: ["only-multiline"]
+type X = [
+number,
+string,
+]
+
+// Options: ["never"]
+type X = []
+
+// Options: ["always"]
+type X = []
+
+// Options: ["always-multiline"]
+type X = []
+
+// Options: ["only-multiline"]
+type X = []
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-generic-spacing"></a>
+### <code>generic-spacing</code>
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent spacing within generic type annotation parameters.
+
+This rule takes one argument. If it is `'never'` then a problem is raised when there is a space surrounding the generic type parameters. If it is `'always'` then a problem is raised when there is no space surrounding the generic type parameters.
+
+The default value is `'never'`.
+
+The following patterns are considered problems:
+
+```js
+type X = Promise< string>
+// Message: There must be no space at start of "Promise" generic type annotation
+
+// Options: ["never"]
+type X = Promise<  string>
+// Message: There must be no space at start of "Promise" generic type annotation
+
+type X = FooBar<string >
+// Message: There must be no space at end of "FooBar" generic type annotation
+
+type X = Promise< string >
+// Message: There must be no space at start of "Promise" generic type annotation
+// Message: There must be no space at end of "Promise" generic type annotation
+
+type X = Promise< (foo), bar, (((baz))) >
+// Message: There must be no space at start of "Promise" generic type annotation
+// Message: There must be no space at end of "Promise" generic type annotation
+
+// Options: ["always"]
+type X = Promise<string >
+// Message: There must be a space at start of "Promise" generic type annotation
+
+// Options: ["always"]
+type X = FooBar< string>
+// Message: There must be a space at end of "FooBar" generic type annotation
+
+// Options: ["always"]
+type X = Promise<string>
+// Message: There must be a space at start of "Promise" generic type annotation
+// Message: There must be a space at end of "Promise" generic type annotation
+
+// Options: ["always"]
+type X = Promise<(foo), bar, (((baz)))>
+// Message: There must be a space at start of "Promise" generic type annotation
+// Message: There must be a space at end of "Promise" generic type annotation
+
+// Options: ["always"]
+type X = FooBar<  string >
+// Message: There must be one space at start of "FooBar" generic type annotation
+
+// Options: ["always"]
+type X = FooBar< string  >
+// Message: There must be one space at end of "FooBar" generic type annotation
+
+// Options: ["always"]
+type X = Promise<  (foo), bar, (((baz)))  >
+// Message: There must be one space at start of "Promise" generic type annotation
+// Message: There must be one space at end of "Promise" generic type annotation
+```
+
+The following patterns are not considered problems:
+
+```js
+type X = Promise<string>
+
+type X = Promise<(string)>
+
+type X = Promise<(foo), bar, (((baz)))>
+
+// Options: ["always"]
+type X = Promise< string >
+
+// Options: ["always"]
+type X = Promise< (string) >
+
+// Options: ["always"]
+type X = Promise< (foo), bar, (((baz))) >
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-no-dupe-keys"></a>
+### <code>no-dupe-keys</code>
+
+Checks for duplicate properties in Object annotations.
+
+This rule mirrors ESLint's [no-dupe-keys](http://eslint.org/docs/rules/no-dupe-keys) rule.
+
+```js
+{
+    "rules": {
+        "flowtype/no-dupe-keys": 2
+    }
+}
+```
+
+The following patterns are considered problems:
+
+```js
+type FooType = { a: number, b: string, a: number }
+// Message: Duplicate property.
+
+type FooType = { a: number, b: string, a: string }
+// Message: Duplicate property.
+```
+
+The following patterns are not considered problems:
+
+```js
+type FooType = { a: number, b: string, c: number }
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-no-weak-types"></a>
+### <code>no-weak-types</code>
+
+Warns against weak type annotations *any*, *Object* and *Function*.
+These types can cause flow to silently skip over portions of your code,
+which would have otherwise caused type errors.
+
+This rule optionally takes one argument, an object to configure which type warnings to enable. By default, all of the
+warnings are enabled. e.g. to disable the `any` warning (allowing it to exist in your code), while continuing to warn
+about `Object` and `Function`:
+
+```js
+{
+    "rules": {
+        "flowtype/no-weak-types": [2, {
+            "any": false,
+            "Object": true,
+            "Function": true
+        }]
+    }
+}
+
+// or, the following is equivalent as default is true:
+
+{
+    "rules": {
+        "flowtype/no-weak-types": [2, {
+            "any": false
+        }]
+    }
+}
+```
+
+The following patterns are considered problems:
+
+```js
+function foo(thing): any {}
+// Message: Unexpected use of weak type "any"
+
+function foo(thing): Promise<any> {}
+// Message: Unexpected use of weak type "any"
+
+function foo(thing): Promise<Promise<any>> {}
+// Message: Unexpected use of weak type "any"
+
+function foo(thing): Object {}
+// Message: Unexpected use of weak type "Object"
+
+function foo(thing): Promise<Object> {}
+// Message: Unexpected use of weak type "Object"
+
+function foo(thing): Promise<Promise<Object>> {}
+// Message: Unexpected use of weak type "Object"
+
+function foo(thing): Function {}
+// Message: Unexpected use of weak type "Function"
+
+function foo(thing): Promise<Function> {}
+// Message: Unexpected use of weak type "Function"
+
+function foo(thing): Promise<Promise<Function>> {}
+// Message: Unexpected use of weak type "Function"
+
+(foo: any) => {}
+// Message: Unexpected use of weak type "any"
+
+(foo: Function) => {}
+// Message: Unexpected use of weak type "Function"
+
+(foo?: any) => {}
+// Message: Unexpected use of weak type "any"
+
+(foo?: Function) => {}
+// Message: Unexpected use of weak type "Function"
+
+(foo: { a: any }) => {}
+// Message: Unexpected use of weak type "any"
+
+(foo: { a: Object }) => {}
+// Message: Unexpected use of weak type "Object"
+
+(foo: any[]) => {}
+// Message: Unexpected use of weak type "any"
+
+type Foo = any
+// Message: Unexpected use of weak type "any"
+
+type Foo = Function
+// Message: Unexpected use of weak type "Function"
+
+type Foo = { a: any }
+// Message: Unexpected use of weak type "any"
+
+type Foo = { a: Object }
+// Message: Unexpected use of weak type "Object"
+
+type Foo = { (a: Object): string }
+// Message: Unexpected use of weak type "Object"
+
+type Foo = { (a: string): Function }
+// Message: Unexpected use of weak type "Function"
+
+function foo(thing: any) {}
+// Message: Unexpected use of weak type "any"
+
+function foo(thing: Object) {}
+// Message: Unexpected use of weak type "Object"
+
+var foo: Function
+// Message: Unexpected use of weak type "Function"
+
+var foo: Object
+// Message: Unexpected use of weak type "Object"
+
+class Foo { props: any }
+// Message: Unexpected use of weak type "any"
+
+class Foo { props: Object }
+// Message: Unexpected use of weak type "Object"
+
+var foo: any
+// Message: Unexpected use of weak type "any"
+
+// Options: [{"Function":false}]
+type X = any; type Y = Function; type Z = Object
+// Message: Unexpected use of weak type "any"
+// Message: Unexpected use of weak type "Object"
+
+// Options: [{"Object":false,"any":false}]
+type X = any; type Y = Function; type Z = Object
+// Message: Unexpected use of weak type "Function"
+```
+
+The following patterns are not considered problems:
+
+```js
+function foo(thing): string {}
+
+function foo(thing): Promise<string> {}
+
+function foo(thing): Promise<Promise<string>> {}
+
+(foo?: string) => {}
+
+(foo: ?string) => {}
+
+(foo: { a: string }) => {}
+
+(foo: { a: ?string }) => {}
+
+(foo: string[]) => {}
+
+type Foo = string
+
+type Foo = { a: string }
+
+type Foo = { (a: string): string }
+
+function foo(thing: string) {}
+
+var foo: string
+
+class Foo { props: string }
+
+// Options: [{"Object":false,"any":false}]
+type X = any; type Y = Object
+
+// Options: [{"Function":false}]
+type X = Function
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-object-type-delimiter"></a>
+### <code>object-type-delimiter</code>
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent separators between properties in Flow object types.
+
+This rule takes one argument.
+
+If it is `'comma'` then a problem is raised when using `;` as a separator.
+
+If it is `'semicolon'` then a problem is raised when using `,` as a separator.
+
+The default value is `'comma'`.
+
+_This rule is ported from `babel/flow-object-type`, however the default option was changed._
+
+The following patterns are considered problems:
+
+```js
+// Options: ["semicolon"]
+type Foo = { a: Foo, b: Bar }
+// Message: Prefer semicolons to commas in object and class types
+
+// Options: ["comma"]
+type Foo = { a: Foo; b: Bar }
+// Message: Prefer commas to semicolons in object and class types
+
+// Options: ["semicolon"]
+type Foo = { [a: string]: Foo, [b: string]: Bar }
+// Message: Prefer semicolons to commas in object and class types
+
+// Options: ["comma"]
+type Foo = { [a: string]: Foo; [b: string]: Bar }
+// Message: Prefer commas to semicolons in object and class types
+
+// Options: ["semicolon"]
+type Foo = { (): Foo, (): Bar }
+// Message: Prefer semicolons to commas in object and class types
+
+// Options: ["comma"]
+type Foo = { (): Foo; (): Bar }
+// Message: Prefer commas to semicolons in object and class types
+
+// Options: ["semicolon"]
+declare class Foo { a: Foo, }
+// Message: Prefer semicolons to commas in object and class types
+
+// Options: ["comma"]
+declare class Foo { a: Foo; }
+// Message: Prefer commas to semicolons in object and class types
+
+// Options: ["semicolon"]
+declare class Foo { [a: string]: Foo, }
+// Message: Prefer semicolons to commas in object and class types
+
+// Options: ["comma"]
+declare class Foo { a: Foo; }
+// Message: Prefer commas to semicolons in object and class types
+
+// Options: ["semicolon"]
+declare class Foo { (): Foo, }
+// Message: Prefer semicolons to commas in object and class types
+
+// Options: ["comma"]
+declare class Foo { (): Foo; }
+// Message: Prefer commas to semicolons in object and class types
+
+// Options: ["semicolon"]
+declare class Foo { static (): Foo, }
+// Message: Prefer semicolons to commas in object and class types
+
+// Options: ["comma"]
+declare class Foo { static (): Foo; }
+// Message: Prefer commas to semicolons in object and class types
+```
+
+The following patterns are not considered problems:
+
+```js
+// Options: ["semicolon"]
+type Foo = { a: Foo; b: Bar }
+
+// Options: ["comma"]
+type Foo = { a: Foo, b: Bar }
+
+// Options: ["semicolon"]
+type Foo = { [a: string]: Foo; [b: string]: Bar }
+
+// Options: ["comma"]
+type Foo = { [a: string]: Foo, [b: string]: Bar }
+
+// Options: ["semicolon"]
+type Foo = { (): Foo; (): Bar }
+
+// Options: ["comma"]
+type Foo = { (): Foo, (): Bar }
+
+type Foo = { a: Foo, b: Bar }
+
+type Foo = { [a: string]: Foo, [b: string]: Bar }
+
+type Foo = { (): Foo, (): Bar }
+
+// Options: ["semicolon"]
+declare class Foo { a: Foo; }
+
+// Options: ["comma"]
+declare class Foo { a: Foo, }
+
+// Options: ["semicolon"]
+declare class Foo { [a: string]: Foo; }
+
+// Options: ["comma"]
+declare class Foo { [a: string]: Foo, }
+
+// Options: ["semicolon"]
+declare class Foo { (): Foo; }
+
+// Options: ["comma"]
+declare class Foo { (): Foo, }
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-require-parameter-type"></a>
+### <code>require-parameter-type</code>
+
+Requires that all function parameters have type annotations.
+
+<a name="eslint-plugin-flowtype-rules-require-parameter-type-options"></a>
+#### Options
+
+You can skip all arrow functions by providing the `excludeArrowFunctions` option with `true`.
+
+Alternatively, you can want to exclude only concise arrow functions (e.g. `x => x * 2`). Provide `excludeArrowFunctions` with `expressionsOnly` for this.
+
+```js
+{
+    "rules": {
+        "flowtype/require-parameter-type": [
+            2,
+            {
+              "excludeArrowFunctions": true
+            }
+        ]
+    }
+}
+
+{
+    "rules": {
+        "flowtype/require-parameter-type": [
+            2,
+            {
+              "excludeArrowFunctions": "expressionsOnly"
+            }
+        ]
+    }
+}
+```
+
+You can exclude parameters that match a certain regex by using `excludeParameterMatch`.
+
+```js
+{
+    "rules": {
+        "flowtype/require-parameter-type": [
+            2,
+            {
+              "excludeParameterMatch": "^_"
+            }
+        ]
+    }
+}
+```
+
+This excludes all parameters that start with an underscore (`_`).
+The default pattern is `a^`, which doesn't match anything, i.e., all parameters are checked.
+
+The following patterns are considered problems:
+
+```js
+(foo) => {}
+// Message: Missing "foo" parameter type annotation.
+
+function x(foo) {}
+// Message: Missing "foo" parameter type annotation.
+
+// Options: [{"excludeArrowFunctions":true}]
+function x(foo) {}
+// Message: Missing "foo" parameter type annotation.
+
+(foo = 'FOO') => {}
+// Message: Missing "foo" parameter type annotation.
+
+(...foo) => {}
+// Message: Missing "foo" parameter type annotation.
+
+({foo}) => {}
+// Message: Missing "{foo}" parameter type annotation.
+
+([foo]) => {}
+// Message: Missing "[foo]" parameter type annotation.
+
+({foo = 1} = {}) => {}
+// Message: Missing "{foo = 1}" parameter type annotation.
+
+// @flow
+(foo) => {}
+// Message: Missing "foo" parameter type annotation.
+
+// Options: [{"excludeArrowFunctions":"expressionsOnly"}]
+(foo) => {}
+// Message: Missing "foo" parameter type annotation.
+
+// Options: [{"excludeArrowFunctions":"expressionsOnly"}]
+function x(foo) {}
+// Message: Missing "foo" parameter type annotation.
+
+// Options: [{"excludeParameterMatch":"^_"}]
+(_foo: number, bar) => {}
+// Message: Missing "bar" parameter type annotation.
+
+// Options: [{"excludeParameterMatch":"^_"}]
+(_foo, bar) => {}
+// Message: Missing "bar" parameter type annotation.
+```
+
+The following patterns are not considered problems:
+
+```js
+(foo: string) => {}
+
+(foo: string = 'FOO') => {}
+
+(...foo: string) => {}
+
+({foo}: {foo: string}) => {}
+
+([foo]: Array) => {}
+
+(foo) => {}
+
+// Options: [{"excludeArrowFunctions":true}]
+(foo) => {}
+
+// Options: [{"excludeArrowFunctions":"expressionsOnly"}]
+(foo) => 3
+
+// Options: [{"excludeParameterMatch":"^_"}]
+(_foo, bar: string) => {}
+
+// Options: [{"excludeParameterMatch":"^_"}]
+(_foo: number, bar: string) => {}
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-require-return-type"></a>
+### <code>require-return-type</code>
+
+Requires that functions have return type annotation.
+
+<a name="eslint-plugin-flowtype-rules-require-return-type-options"></a>
+#### Options
+
+You can skip all arrow functions by providing the `excludeArrowFunctions` option with `true`.
+
+Alternatively, you can want to exclude only concise arrow function (e.g. `() => 2`). Provide `excludeArrowFunctions` with `expressionsOnly` for this.
+
+```js
+{
+    "rules": {
+        "flowtype/require-return-type": [
+            2,
+            "always",
+            {
+              "excludeArrowFunctions": true
+            }
+        ]
+    }
+}
+
+{
+    "rules": {
+        "flowtype/require-return-type": [
+            2,
+            "always",
+            {
+              "excludeArrowFunctions": "expressionsOnly"
+            }
+        ]
+    }
+}
+```
+
+The following patterns are considered problems:
+
+```js
+(foo) => { return "foo"; }
+// Message: Missing return type annotation.
+
+// Options: ["always"]
+(foo) => { return "foo"; }
+// Message: Missing return type annotation.
+
+// Options: ["always"]
+(foo) => "foo"
+// Message: Missing return type annotation.
+
+(foo) => ({})
+// Message: Missing return type annotation.
+
+(foo): undefined => { return; }
+// Message: Must not annotate undefined return type.
+
+(foo): void => { return; }
+// Message: Must not annotate undefined return type.
+
+(foo): undefined => { return undefined; }
+// Message: Must not annotate undefined return type.
+
+(foo): void => { return void 0; }
+// Message: Must not annotate undefined return type.
+
+// Options: ["always",{"annotateUndefined":"never"}]
+(foo): undefined => { return; }
+// Message: Must not annotate undefined return type.
+
+// Options: ["always",{"annotateUndefined":"never"}]
+(foo): void => { return; }
+// Message: Must not annotate undefined return type.
+
+// Options: ["always",{"annotateUndefined":"always"}]
+(foo) => { return; }
+// Message: Must annotate undefined return type.
+
+// Options: ["always",{"annotateUndefined":"never"}]
+(foo): undefined => { return undefined; }
+// Message: Must not annotate undefined return type.
+
+// Options: ["always",{"annotateUndefined":"always"}]
+(foo) => { return undefined; }
+// Message: Must annotate undefined return type.
+
+// Options: ["always",{"annotateUndefined":"always"}]
+(foo) => { return void 0; }
+// Message: Must annotate undefined return type.
+
+// @flow
+(foo) => { return 1; }
+// Message: Missing return type annotation.
+
+// Options: ["always",{"annotateUndefined":"always"}]
+// @flow
+ (foo) => { return undefined; }
+// Message: Must annotate undefined return type.
+
+// Options: ["always"]
+async () => { return 2; }
+// Message: Missing return type annotation.
+
+// Options: ["always",{"annotateUndefined":"always"}]
+async () => {}
+// Message: Missing return type annotation.
+
+// Options: ["always",{"annotateUndefined":"always"}]
+async function x() {}
+// Message: Missing return type annotation.
+
+// Options: ["always"]
+async () => { return; }
+// Message: Missing return type annotation.
+
+// Options: ["always"]
+function* x() {}
+// Message: Missing return type annotation.
+
+// Options: ["always",{"excludeArrowFunctions":"expressionsOnly"}]
+() => { return 3; }
+// Message: Missing return type annotation.
+
+// Options: ["always",{"excludeArrowFunctions":"expressionsOnly"}]
+async () => { return 4; }
+// Message: Missing return type annotation.
+```
+
+The following patterns are not considered problems:
+
+```js
+(foo): string => {}
+
+// Options: ["always"]
+(foo): string => {}
+
+(foo) => { return; }
+
+(foo): Object => ( {} )
+
+(foo) => { return undefined; }
+
+(foo) => { return void 0; }
+
+// Options: ["always",{"annotateUndefined":"always"}]
+(foo): undefined => { return; }
+
+// Options: ["always",{"annotateUndefined":"always"}]
+(foo): void => { return; }
+
+// Options: ["always",{"annotateUndefined":"never"}]
+(foo) => { return; }
+
+// Options: ["always",{"annotateUndefined":"never"}]
+(foo) => { return undefined; }
+
+// Options: ["always",{"annotateUndefined":"never"}]
+(foo) => { return void 0; }
+
+// Options: ["always",{"annotateUndefined":"always"}]
+(foo): undefined => { return undefined; }
+
+// Options: ["always",{"annotateUndefined":"always"}]
+(foo): void => { return void 0; }
+
+// Options: ["always"]
+(foo) => { return 1; }
+
+// Options: ["always",{"annotateUndefined":"always"}]
+(foo) => { return undefined; }
+
+// Options: ["always",{"annotateUndefined":"always"}]
+async function doThing(): Promise<void> {}
+
+// Options: ["always",{"annotateUndefined":"always"}]
+function* doThing(): Generator<number, void, void> { yield 2; }
+
+async (foo): Promise<number> => { return 3; }
+
+// Options: ["always",{"excludeArrowFunctions":true}]
+() => 3
+
+// Options: ["always",{"excludeArrowFunctions":true}]
+() => { return 4; }
+
+// Options: ["always",{"excludeArrowFunctions":true}]
+() => undefined
+
+// Options: ["always",{"annotateUndefined":"always","excludeArrowFunctions":true}]
+() => undefined
+
+// Options: ["always",{"annotateUndefined":"always","excludeArrowFunctions":true}]
+() => { return undefined; }
+
+// Options: ["always",{"excludeArrowFunctions":"expressionsOnly"}]
+() => 3
+
+// Options: ["always",{"excludeArrowFunctions":"expressionsOnly"}]
+async () => 3
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-require-valid-file-annotation"></a>
+### <code>require-valid-file-annotation</code>
+
+This rule validates Flow file annotations.
+
+This rule can optionally report missing or missed placed annotations, common typos (e.g. `// @floww`), and enforce a consistant annotation style.
+
+<a name="eslint-plugin-flowtype-rules-require-valid-file-annotation-options"></a>
+#### Options
+
+The rule has a string option:
+
+* `"never"` (default): Never report files that are missing an `@flow` annotation.
+* `"always"`: Always report files that are missing an `@flow` annotation
+
+This rule has an object option:
+
+* `"annotationStyle"` - Enforce a consistant file annotation style.
+    * `"none"` (default): Either annotation style is accepted.
+    * `"line"`: Require single line annotations (i.e. `// @flow`).
+    * `"block"`: Require block annotations (i.e. `/* @flow */`).
+
+```js
+{
+  "rules": {
+    "flowtype/require-valid-file-annotation": [
+      2,
+      "always"
+    ]
+  }
+}
+
+{
+  "rules": {
+    "flowtype/require-valid-file-annotation": [
+      2,
+      "always", {
+        "annotationStyle": "block"
+      }
+    ]
+  }
+}
+```
+
+The following patterns are considered problems:
+
+```js
+;// @flow
+// Message: Flow file annotation not at the top of the file.
+
+;
+// @flow
+// Message: Flow file annotation not at the top of the file.
+
+// @Flow
+// Message: Malformed flow file annotation.
+
+// @floweeeeeee
+// Message: Malformed flow file annotation.
+
+// @NoFlow
+// Message: Malformed flow file annotation.
+
+// @nofloweeeeeee
+// Message: Malformed flow file annotation.
+
+// Options: ["always"]
+a;
+// Message: Flow file annotation is missing.
+
+// Options: ["always",{"annotationStyle":"line"}]
+/* @flow */
+// Message: Flow file annotation style must be `// @flow`
+
+// Options: ["always",{"annotationStyle":"block"}]
+// @flow
+// Message: Flow file annotation style must be `/* @flow */`
+```
+
+The following patterns are not considered problems:
+
+```js
+a;
+
+// @flow
+a;
+
+//@flow
+a;
+
+//**@flow
+a;
+
+/* foo @flow bar */
+a;
+
+
+
+// @flow
+a;
+
+// @flow
+// @FLow
+
+// @noflow
+a;
+
+// Options: ["always"]
+a;
+
+// Options: ["always",{"annotationStyle":"line"}]
+// @flow
+
+// Options: ["always",{"annotationStyle":"block"}]
+/* @flow */
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-semi"></a>
+### <code>semi</code>
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent use of semicolons after type aliases.
+
+This rule takes one argument. If it is `'never'` then a problem is raised when there is a semicolon after a type alias. If it is `'always'` then a problem is raised when there is no semicolon after a type alias.
+
+The default value is `'always'`.
+
+The following patterns are considered problems:
+
+```js
+// Options: []
+type FooType = {}
+// Message: Missing semicolon.
+
+// Options: ["always"]
+type FooType = {}
+// Message: Missing semicolon.
+
+// Options: ["never"]
+type FooType = {};
+// Message: Extra semicolon.
+```
+
+The following patterns are not considered problems:
+
+```js
+type FooType = {};
+
+// Options: ["always"]
+type FooType = {};
+
+// Options: ["always"]
+type FooType = { a: number;
+ b: string;
+ };
+
+// Options: ["never"]
+type FooType = { a: number;
+ b: string;
+ }
+
+// Options: ["never"]
+type FooType = {}
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-sort-keys"></a>
+### <code>sort-keys</code>
+
+Enforces sorting of Object annotations.
+
+This rule mirrors ESlint's [sort-keys](http://eslint.org/docs/rules/sort-keys) rule.
+
+<a name="eslint-plugin-flowtype-rules-sort-keys-options"></a>
+#### Options
+
+The first option specifies sort order.
+
+* `"asc"` (default) - enforce ascending sort order.
+* `"desc"` - enforce descending sort order.
+
+The second option takes an object with two possible properties.
+
+* `caseSensitive` - if `true`, enforce case-sensitive sort order. Default is `true`.
+* `natural` - if `true`, enforce [natural sort order](https://en.wikipedia.org/wiki/Natural_sort_order). Default is `false`.
+
+```js
+{
+  "rules": {
+    "flowtype/sort-keys": [
+      2,
+      "asc", {
+        "caseSensitive": true,
+        "natural": false
+      }
+    ]
+  }
+}
+```
+
+The following patterns are considered problems:
+
+```js
+type FooType = { a: number, c: number, b: string }
+// Message: Expected type annotations to be in ascending order. "b" should be before "c".
+
+type FooType = { a: number, b: number, C: number }
+// Message: Expected type annotations to be in ascending order. "C" should be before "b".
+
+type FooType = { 1: number, 2: number, 10: number }
+// Message: Expected type annotations to be in ascending order. "10" should be before "2".
+
+// Options: ["desc"]
+type FooType = { a: number, b: number }
+// Message: Expected type annotations to be in descending order. "b" should be before "a".
+
+// Options: ["desc"]
+type FooType = { C: number, b: number, a: string }
+// Message: Expected type annotations to be in descending order. "b" should be before "C".
+
+// Options: ["desc"]
+type FooType = { 10: number, 2: number, 1: number }
+// Message: Expected type annotations to be in descending order. "2" should be before "10".
+
+// Options: ["asc",{"caseSensitive":false}]
+type FooType = { a: number, c: number, C: number, b: string }
+// Message: Expected type annotations to be in insensitive ascending order. "b" should be before "C".
+
+// Options: ["asc",{"caseSensitive":false}]
+type FooType = { a: number, C: number, c: number, b: string }
+// Message: Expected type annotations to be in insensitive ascending order. "b" should be before "c".
+
+// Options: ["asc",{"natural":true}]
+type FooType = { 1: number, 10: number, 2: boolean }
+// Message: Expected type annotations to be in natural ascending order. "2" should be before "10".
+```
+
+The following patterns are not considered problems:
+
+```js
+type FooType = { a: number }
+
+type FooType = { a: number, b: number, c: (boolean | number) }
+
+type FooType = { C: number, a: string, b: foo }
+
+type FooType = { 1: number, 10: number, 2: boolean }
+
+// Options: ["desc"]
+type FooType = { c: number, b: number, a: number }
+
+// Options: ["desc"]
+type FooType = { b: string, a: {}, C: number }
+
+// Options: ["desc"]
+type FooType = { 2: number, 10: number, 1: boolean }
+
+// Options: ["asc",{"caseSensitive":false}]
+type FooType = { a: number, b: number, c: number, C: number }
+
+// Options: ["asc",{"caseSensitive":false}]
+type FooType = { a: number, b: number, C: number, c: number }
+
+// Options: ["asc",{"natural":true}]
+type FooType = { 1:number, 2: number, 10: number }
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-space-after-type-colon"></a>
+### <code>space-after-type-colon</code>
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent spacing after the type annotation colon.
+
+This rule takes one argument. If it is `'always'` then a problem is raised when there is no space after the type annotation colon. If it is `'never'` then a problem is raised when there is a space after the type annotation colon. The default value is `'always'`.
+
+The following patterns are considered problems:
+
+```js
+// Options: ["never"]
+(foo: string) => {}
+// Message: There must be no space after "foo" parameter type annotation colon.
+
+// Options: ["always"]
+(foo:  string) => {}
+// Message: There must be 1 space after "foo" parameter type annotation colon.
+
+// Options: ["always"]
+(foo:(() => void)) => {}
+// Message: There must be a space after "foo" parameter type annotation colon.
+
+// Options: ["never"]
+(foo: (() => void)) => {}
+// Message: There must be no space after "foo" parameter type annotation colon.
+
+// Options: ["always"]
+(foo:  (() => void)) => {}
+// Message: There must be 1 space after "foo" parameter type annotation colon.
+
+({ lorem, ipsum, dolor } :   SomeType) => {}
+// Message: There must be 1 space after "{ lorem, ipsum, dolor }" parameter type annotation colon.
+
+(foo:{ a: string, b: number }) => {}
+// Message: There must be a space after "foo" parameter type annotation colon.
+
+({ a, b } :{ a: string, b: number }) => {}
+// Message: There must be a space after "{ a, b }" parameter type annotation colon.
+
+([ a, b ] :string[]) => {}
+// Message: There must be a space after "[ a, b ]" parameter type annotation colon.
+
+(i?:number) => {}
+// Message: There must be a space after "i" parameter type annotation colon.
+
+(i?:  number) => {}
+// Message: There must be 1 space after "i" parameter type annotation colon.
+
+// Options: ["never"]
+(i?: number) => {}
+// Message: There must be no space after "i" parameter type annotation colon.
+
+// Options: ["always"]
+():Object => {}
+// Message: There must be a space after return type colon.
+
+// Options: ["never"]
+(): Object => {}
+// Message: There must be no space after return type colon.
+
+// Options: ["always"]
+():  Object => {}
+// Message: There must be 1 space after return type colon.
+
+// Options: ["always"]
+():(() => void) => {}
+// Message: There must be a space after return type colon.
+
+// Options: ["never"]
+(): (() => void) => {}
+// Message: There must be no space after return type colon.
+
+// Options: ["always"]
+():  (() => void) => {}
+// Message: There must be 1 space after return type colon.
+
+// Options: ["never"]
+export default function (foo: string) {}
+// Message: There must be no space after "foo" parameter type annotation colon.
+
+// Options: ["never"]
+function foo (foo: string) {}
+// Message: There must be no space after "foo" parameter type annotation colon.
+
+// Options: ["always"]
+(foo:string) => {}
+// Message: There must be a space after "foo" parameter type annotation colon.
+
+function foo (foo:string) {}
+// Message: There must be a space after "foo" parameter type annotation colon.
+
+async function foo({ lorem, ipsum, dolor }:SomeType) {}
+// Message: There must be a space after "{ lorem, ipsum, dolor }" parameter type annotation colon.
+
+function x(i?:number) {}
+// Message: There must be a space after "i" parameter type annotation colon.
+
+function x(i?:  number) {}
+// Message: There must be 1 space after "i" parameter type annotation colon.
+
+// Options: ["never"]
+function x(i?: number) {}
+// Message: There must be no space after "i" parameter type annotation colon.
+
+function a():x {}
+// Message: There must be a space after return type colon.
+
+// Options: ["always"]
+function a():  x {}
+// Message: There must be 1 space after return type colon.
+
+// Options: ["never"]
+function a(): x {}
+// Message: There must be no space after return type colon.
+
+type X = (foo:number) => string
+// Message: There must be a space after "foo" parameter type annotation colon.
+
+// Options: ["never"]
+type X = (foo: number) => string
+// Message: There must be no space after "foo" parameter type annotation colon.
+
+type X = (foo:  number) => string
+// Message: There must be 1 space after "foo" parameter type annotation colon.
+
+type X = (foo:?number) => string
+// Message: There must be a space after "foo" parameter type annotation colon.
+
+type X = (foo:(number)) => string
+// Message: There must be a space after "foo" parameter type annotation colon.
+
+type X = (foo:((number))) => string
+// Message: There must be a space after "foo" parameter type annotation colon.
+
+type X = (foo:  ((number))) => string
+// Message: There must be 1 space after "foo" parameter type annotation colon.
+
+// Options: ["never"]
+type X = (foo: ((number))) => string
+// Message: There must be no space after "foo" parameter type annotation colon.
+
+type X = (foo:?(number)) => string
+// Message: There must be a space after "foo" parameter type annotation colon.
+
+type TArrayPredicate = (el: T, i?:number) => boolean
+// Message: There must be a space after "i" parameter type annotation colon.
+
+type TArrayPredicate = (el: T, i?:  number) => boolean
+// Message: There must be 1 space after "i" parameter type annotation colon.
+
+// Options: ["never"]
+type TArrayPredicate = (el:T, i?: number) => boolean
+// Message: There must be no space after "i" parameter type annotation colon.
+
+class X { foo:string }
+// Message: There must be a space after "foo" class property type annotation colon.
+
+// Options: ["never"]
+class X { foo: string }
+// Message: There must be no space after "foo" class property type annotation colon.
+
+class X { foo:?string }
+// Message: There must be a space after "foo" class property type annotation colon.
+
+// Options: ["never"]
+class X { foo: ?string }
+// Message: There must be no space after "foo" class property type annotation colon.
+
+class X { static foo:number }
+// Message: There must be a space after "foo" class property type annotation colon.
+
+// Options: ["never"]
+class X { static foo: number }
+// Message: There must be no space after "foo" class property type annotation colon.
+
+class X { static foo :number }
+// Message: There must be a space after "foo" class property type annotation colon.
+
+// Options: ["never"]
+class X { static foo : number }
+// Message: There must be no space after "foo" class property type annotation colon.
+
+declare class X { static foo:number }
+// Message: There must be a space after "foo" type annotation colon.
+
+// Options: ["never"]
+declare class X { static foo: number }
+// Message: There must be no space after "foo" type annotation colon.
+
+declare class X { static foo :number }
+// Message: There must be a space after "foo" type annotation colon.
+
+// Options: ["never"]
+declare class X { static foo : number }
+// Message: There must be no space after "foo" type annotation colon.
+
+class X { +foo:string }
+// Message: There must be a space after "foo" class property type annotation colon.
+
+class X { +foo:  string }
+// Message: There must be 1 space after "foo" class property type annotation colon.
+
+// Options: ["never"]
+class X { +foo: string }
+// Message: There must be no space after "foo" class property type annotation colon.
+
+class X { static +foo:string }
+// Message: There must be a space after "foo" class property type annotation colon.
+
+class X { static +foo:  string }
+// Message: There must be 1 space after "foo" class property type annotation colon.
+
+// Options: ["never"]
+class X { static +foo: string }
+// Message: There must be no space after "foo" class property type annotation colon.
+
+type X = { foo:string }
+// Message: There must be a space after "foo" type annotation colon.
+
+// Options: ["always"]
+type X = { foo:string }
+// Message: There must be a space after "foo" type annotation colon.
+
+// Options: ["never"]
+type X = { foo: string }
+// Message: There must be no space after "foo" type annotation colon.
+
+type X = { foo:  string }
+// Message: There must be 1 space after "foo" type annotation colon.
+
+type X = { foo?:string }
+// Message: There must be a space after "foo" type annotation colon.
+
+// Options: ["never"]
+type X = { foo?: string }
+// Message: There must be no space after "foo" type annotation colon.
+
+type X = { foo?:?string }
+// Message: There must be a space after "foo" type annotation colon.
+
+type X = { foo?:  ?string }
+// Message: There must be 1 space after "foo" type annotation colon.
+
+type Foo = { barType:(string | () => void) }
+// Message: There must be a space after "barType" type annotation colon.
+
+type Foo = { barType:(((string | () => void))) }
+// Message: There must be a space after "barType" type annotation colon.
+
+// Options: ["never"]
+type Foo = { barType: (string | () => void) }
+// Message: There must be no space after "barType" type annotation colon.
+
+type Foo = { barType:  (string | () => void) }
+// Message: There must be 1 space after "barType" type annotation colon.
+
+type Foo = { barType:  ((string | () => void)) }
+// Message: There must be 1 space after "barType" type annotation colon.
+
+type X = { get:() => A; }
+// Message: There must be a space after "get" type annotation colon.
+
+type X = { get:<X>() => A; }
+// Message: There must be a space after "get" type annotation colon.
+
+// Options: ["never"]
+type X = { get: () => A; }
+// Message: There must be no space after "get" type annotation colon.
+
+// Options: ["never"]
+type X = { get: <X>() => A; }
+// Message: There must be no space after "get" type annotation colon.
+
+type X = { get:  () => A; }
+// Message: There must be 1 space after "get" type annotation colon.
+
+type X = { get:  <X>() => A; }
+// Message: There must be 1 space after "get" type annotation colon.
+
+type X = { +foo:string }
+// Message: There must be a space after "foo" type annotation colon.
+
+type X = { +foo:  string }
+// Message: There must be 1 space after "foo" type annotation colon.
+
+// Options: ["never"]
+type X = { +foo: string }
+// Message: There must be no space after "foo" type annotation colon.
+
+type X = { +foo?:string }
+// Message: There must be a space after "foo" type annotation colon.
+
+type X = { +foo?:  string }
+// Message: There must be 1 space after "foo" type annotation colon.
+
+// Options: ["never"]
+type X = { +foo?: string }
+// Message: There must be no space after "foo" type annotation colon.
+
+// Options: ["always"]
+type X = { [a:b]: c }
+// Message: There must be a space after type annotation colon.
+
+// Options: ["never"]
+type X = { [a: b]:c }
+// Message: There must be no space after type annotation colon.
+
+// Options: ["always"]
+type X = { [a:    b]: c }
+// Message: There must be 1 space after type annotation colon.
+
+// Options: ["always"]
+type X = { +[a:b]: c }
+// Message: There must be a space after type annotation colon.
+
+// Options: ["never"]
+type X = { +[a: b]:c }
+// Message: There must be no space after type annotation colon.
+
+// Options: ["always"]
+type X = { +[a:    b]: c }
+// Message: There must be 1 space after type annotation colon.
+
+// Options: ["always"]
+type X = { [a: b]:c }
+// Message: There must be a space after type annotation colon.
+
+// Options: ["never"]
+type X = { [a:b]: c }
+// Message: There must be no space after type annotation colon.
+
+// Options: ["always"]
+type X = { [a: b]:    c }
+// Message: There must be 1 space after type annotation colon.
+
+// Options: ["always"]
+type X = { [a:b]:c }
+// Message: There must be a space after type annotation colon.
+// Message: There must be a space after type annotation colon.
+
+// Options: ["never"]
+type X = { [a: b]: c }
+// Message: There must be no space after type annotation colon.
+// Message: There must be no space after type annotation colon.
+
+// Options: ["always"]
+type X = { [a:  b]:  c }
+// Message: There must be 1 space after type annotation colon.
+// Message: There must be 1 space after type annotation colon.
+
+// Options: ["always"]
+type X = { [a:(b)]:(c) }
+// Message: There must be a space after type annotation colon.
+// Message: There must be a space after type annotation colon.
+
+// Options: ["never"]
+type X = { [a: (b)]: (c) }
+// Message: There must be no space after type annotation colon.
+// Message: There must be no space after type annotation colon.
+
+// Options: ["never"]
+const x = ({}: {})
+// Message: There must be no space after type cast colon.
+
+// Options: ["always"]
+const x = ({}:{})
+// Message: There must be a space after type cast colon.
+
+// Options: ["always"]
+const x = ({}:  {})
+// Message: There must be 1 space after type cast colon.
+
+// Options: ["never"]
+((x): (string))
+// Message: There must be no space after type cast colon.
+
+// Options: ["always"]
+((x):(string))
+// Message: There must be a space after type cast colon.
+
+// Options: ["always"]
+((x):  (string))
+// Message: There must be 1 space after type cast colon.
+```
+
+The following patterns are not considered problems:
+
+```js
+(foo) => {}
+
+(foo: string) => {}
+
+(foo: (string|number)) => {}
+
+// Options: ["never"]
+(foo:string) => {}
+
+// Options: ["always"]
+(foo: string) => {}
+
+// Options: ["never"]
+(foo:(() => void)) => {}
+
+// Options: ["always"]
+(foo: (() => void)) => {}
+
+({ lorem, ipsum, dolor }: SomeType) => {}
+
+(foo: { a: string, b: number }) => {}
+
+({ a, b }: ?{ a: string, b: number }) => {}
+
+([ a, b ]: string[]) => {}
+
+(i?: number) => {}
+
+// Options: ["never"]
+(i?:number) => {}
+
+// Options: ["never"]
+():Object => {}
+
+// Options: ["always"]
+(): Object => {}
+
+// Options: ["never"]
+():(number | string) => {}
+
+// Options: ["always"]
+(): (number | string) => {}
+
+// Options: ["never"]
+():number|string => {}
+
+// Options: ["always"]
+(): number|string => {}
+
+// Options: ["never"]
+():(() => void) => {}
+
+// Options: ["always"]
+(): (() => void) => {}
+
+// Options: ["never"]
+():( () => void ) => {}
+
+// Options: ["always"]
+(): ( () => void ) => {}
+
+(): { a: number, b: string } => {}
+
+// Options: ["never"]
+() :{ a:number, b:string } => {}
+
+function x(foo: string) {}
+
+class Foo { constructor(foo: string) {} }
+
+// Options: ["never"]
+function x(foo:string) {}
+
+// Options: ["never"]
+class Foo { constructor(foo:string) {} }
+
+async function foo({ lorem, ipsum, dolor }: SomeType) {}
+
+function x({ a, b }: { a: string, b: number }) {}
+
+function x(i?: number) {}
+
+// Options: ["never"]
+function x(i?:number) {}
+
+function a(): x {}
+
+// Options: ["never"]
+function a():x {}
+
+function a(): (number | string) {}
+
+// Options: ["never"]
+function a() :(number | string) {}
+
+type X = (foo: number) => string;
+
+type X = (foo : number) => string;
+
+type X = (foo: ?number) => string;
+
+type X = (foo? : ?number) => string;
+
+type X = (foo: ?{ x: number }) => string;
+
+// Options: ["never"]
+type X = (foo:number) => string;
+
+// Options: ["never"]
+type X = (foo:?{ x:number }) => string;
+
+type X = (foo: (number)) => string
+
+type X = (foo: ((number))) => string
+
+// Options: ["never"]
+type X = (foo:((number))) => string
+
+type X = ?(foo: ((number))) => string
+
+// Options: ["never"]
+type X = ?(foo:((number))) => string
+
+type TArrayPredicate = (el: T, i?: number) => boolean
+
+// Options: ["never"]
+type TArrayPredicate = (el:T, i?:number) => boolean
+
+class Foo { bar }
+
+class Foo { bar = 3 }
+
+class Foo { bar: string }
+
+class Foo { bar: ?string }
+
+// Options: ["never"]
+class Foo { bar:string }
+
+// Options: ["never"]
+class Foo { bar:?string }
+
+class X { static foo : number }
+
+// Options: ["never"]
+class X { static foo :number }
+
+declare class X { static foo : number }
+
+// Options: ["never"]
+declare class X { static foo :number }
+
+class X { +foo: string }
+
+class X { static +foo: string }
+
+// Options: ["never"]
+class X { +foo:string }
+
+// Options: ["never"]
+class X { static +foo:string }
+
+type X = { foo: string }
+
+// Options: ["never"]
+type X = { foo:string }
+
+type X = { foo?: string }
+
+type X = { foo?: ?string }
+
+// Options: ["never"]
+type X = { foo?:?string }
+
+type Foo = { barType: (string | () => void) }
+
+type Foo = { barType: ((string | () => void)) }
+
+// Options: ["never"]
+type Foo = { barType:(string | () => void) }
+
+// Options: ["never"]
+type Foo = { barType:((string | () => void)) }
+
+type X = { get(): A; }
+
+type X = { get<X>(): A; }
+
+// Options: ["never"]
+type X = { get(): A; }
+
+// Options: ["never"]
+type X = { get<X>(): A; }
+
+type X = { get: () => A; }
+
+type X = { get: <X>() => A; }
+
+// Options: ["never"]
+type X = { get:() => A; }
+
+// Options: ["never"]
+type X = { get:<X>() => A; }
+
+type X = { +foo: string }
+
+type X = { +foo?: string }
+
+// Options: ["never"]
+type X = { +foo:string }
+
+// Options: ["never"]
+type X = { +foo?:string }
+
+// Options: ["always"]
+type X = { [a: b]: c }
+
+// Options: ["never"]
+type X = { [a:b]:c }
+
+// Options: ["always"]
+type X = { +[a: b]: c }
+
+// Options: ["never"]
+type X = { +[a:b]:c }
+
+// Options: ["never"]
+const x = ({}:{})
+
+// Options: ["always"]
+const x = ({}: {})
+
+// Options: ["never"]
+((x):(string))
+
+// Options: ["always"]
+((x): (string))
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-space-before-generic-bracket"></a>
+### <code>space-before-generic-bracket</code>
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent spacing before the opening `<` of generic type annotation parameters.
+
+This rule takes one argument. If it is `'never'` then a problem is raised when there is a space before the `<`. If it is `'always'` then a problem is raised when there is no space before the `<`.
+
+The default value is `'never'`.
+
+The following patterns are considered problems:
+
+```js
+type X = Promise <string>
+// Message: There must be no space before "Promise" generic type annotation bracket
+
+// Options: ["never"]
+type X = Promise <string>
+// Message: There must be no space before "Promise" generic type annotation bracket
+
+type X = Promise  <string>
+// Message: There must be no space before "Promise" generic type annotation bracket
+
+// Options: ["always"]
+type X = Promise<string>
+// Message: There must be a space before "Promise" generic type annotation bracket
+
+// Options: ["always"]
+type X = Promise  <string>
+// Message: There must be one space before "Promise" generic type annotation bracket
+```
+
+The following patterns are not considered problems:
+
+```js
+type X = Promise<string>
+
+// Options: ["always"]
+type X = Promise <string>
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-space-before-type-colon"></a>
+### <code>space-before-type-colon</code>
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent spacing before the type annotation colon.
+
+This rule takes one argument. If it is `'always'` then a problem is raised when there is no space before the type annotation colon. If it is `'never'` then a problem is raised when there is a space before the type annotation colon. The default value is `'never'`.
+
+The following patterns are considered problems:
+
+```js
+// Options: ["never"]
+(foo : string) => {}
+// Message: There must be no space before "foo" parameter type annotation colon.
+
+// Options: ["never"]
+(foo ? : string) => {}
+// Message: There must be no space before "foo" parameter type annotation colon.
+
+// Options: ["always"]
+(foo: string) => {}
+// Message: There must be a space before "foo" parameter type annotation colon.
+
+// Options: ["always"]
+(foo  : string) => {}
+// Message: There must be 1 space before "foo" parameter type annotation colon.
+
+// Options: ["always"]
+(foo?: string) => {}
+// Message: There must be a space before "foo" parameter type annotation colon.
+
+// Options: ["always"]
+(foo ?  : string) => {}
+// Message: There must be 1 space before "foo" parameter type annotation colon.
+
+// Options: ["always"]
+(foo  ?: string) => {}
+// Message: There must be a space before "foo" parameter type annotation colon.
+
+({ lorem, ipsum, dolor } : SomeType) => {}
+// Message: There must be no space before "{ lorem, ipsum, dolor }" parameter type annotation colon.
+
+(foo : { a: string, b: number }) => {}
+// Message: There must be no space before "foo" parameter type annotation colon.
+
+({ a, b } : { a: string, b: number }) => {}
+// Message: There must be no space before "{ a, b }" parameter type annotation colon.
+
+([ a, b ] : string[]) => {}
+// Message: There must be no space before "[ a, b ]" parameter type annotation colon.
+
+() : x => {}
+// Message: There must be no space before return type colon.
+
+// Options: ["always"]
+(): x => {}
+// Message: There must be a space before return type colon.
+
+// Options: ["always"]
+()  : x => {}
+// Message: There must be 1 space before return type colon.
+
+function x(foo : string) {}
+// Message: There must be no space before "foo" parameter type annotation colon.
+
+// Options: ["always"]
+function x(foo: string) {}
+// Message: There must be a space before "foo" parameter type annotation colon.
+
+var x = function (foo : string) {}
+// Message: There must be no space before "foo" parameter type annotation colon.
+
+// Options: ["always"]
+var x = function (foo: string) {}
+// Message: There must be a space before "foo" parameter type annotation colon.
+
+class Foo { constructor(foo : string ) {} }
+// Message: There must be no space before "foo" parameter type annotation colon.
+
+// Options: ["always"]
+class Foo { constructor(foo: string ) {} }
+// Message: There must be a space before "foo" parameter type annotation colon.
+
+async function foo({ lorem, ipsum, dolor } : SomeType) {}
+// Message: There must be no space before "{ lorem, ipsum, dolor }" parameter type annotation colon.
+
+function a() : x {}
+// Message: There must be no space before return type colon.
+
+// Options: ["always"]
+function a(): x {}
+// Message: There must be a space before return type colon.
+
+// Options: ["always"]
+function a()  : x {}
+// Message: There must be 1 space before return type colon.
+
+type X = (foo :string) => string;
+// Message: There must be no space before "foo" parameter type annotation colon.
+
+// Options: ["always"]
+type X = (foo:string) => string;
+// Message: There must be a space before "foo" parameter type annotation colon.
+
+// Options: ["always"]
+type X = (foo  :string) => string;
+// Message: There must be 1 space before "foo" parameter type annotation colon.
+
+type X = (foo? :string) => string;
+// Message: There must be no space before "foo" parameter type annotation colon.
+
+type X = (foo?     :string) => string;
+// Message: There must be no space before "foo" parameter type annotation colon.
+
+// Options: ["always"]
+type X = (foo?:string) => string;
+// Message: There must be a space before "foo" parameter type annotation colon.
+
+type X = (foo? :?string) => string;
+// Message: There must be no space before "foo" parameter type annotation colon.
+
+class X { foo :string }
+// Message: There must be no space before "foo" class property type annotation colon.
+
+// Options: ["always"]
+class X { foo: string }
+// Message: There must be a space before "foo" class property type annotation colon.
+
+class X { foo :?string }
+// Message: There must be no space before "foo" class property type annotation colon.
+
+// Options: ["always"]
+class X { foo: ?string }
+// Message: There must be a space before "foo" class property type annotation colon.
+
+class X { static foo : number }
+// Message: There must be no space before "foo" class property type annotation colon.
+
+class X { static foo :number }
+// Message: There must be no space before "foo" class property type annotation colon.
+
+// Options: ["always"]
+class X { static foo: number }
+// Message: There must be a space before "foo" class property type annotation colon.
+
+// Options: ["always"]
+class X { static foo:number }
+// Message: There must be a space before "foo" class property type annotation colon.
+
+declare class Foo { static bar :number; }
+// Message: There must be no space before "bar" type annotation colon.
+
+declare class Foo { static bar : number; }
+// Message: There must be no space before "bar" type annotation colon.
+
+// Options: ["always"]
+declare class Foo { static bar:number; }
+// Message: There must be a space before "bar" type annotation colon.
+
+// Options: ["always"]
+declare class Foo { static bar: number; }
+// Message: There must be a space before "bar" type annotation colon.
+
+// Options: ["always"]
+class X { +foo: string }
+// Message: There must be a space before "foo" class property type annotation colon.
+
+// Options: ["always"]
+class X { +foo  : string }
+// Message: There must be 1 space before "foo" class property type annotation colon.
+
+// Options: ["never"]
+class X { +foo : string }
+// Message: There must be no space before "foo" class property type annotation colon.
+
+// Options: ["always"]
+class X { static +foo: string }
+// Message: There must be a space before "foo" class property type annotation colon.
+
+// Options: ["always"]
+class X { static +foo  : string }
+// Message: There must be 1 space before "foo" class property type annotation colon.
+
+// Options: ["never"]
+class X { static +foo : string }
+// Message: There must be no space before "foo" class property type annotation colon.
+
+type X = { foo : string }
+// Message: There must be no space before "foo" type annotation colon.
+
+// Options: ["never"]
+type X = { foo : string }
+// Message: There must be no space before "foo" type annotation colon.
+
+// Options: ["always"]
+type X = { foo: string }
+// Message: There must be a space before "foo" type annotation colon.
+
+// Options: ["always"]
+type X = { foo  : string }
+// Message: There must be 1 space before "foo" type annotation colon.
+
+type X = { foo? : string }
+// Message: There must be no space before "foo" type annotation colon.
+
+// Options: ["always"]
+type X = { foo?: string }
+// Message: There must be a space before "foo" type annotation colon.
+
+// Options: ["always"]
+type X = { foo?  : string }
+// Message: There must be 1 space before "foo" type annotation colon.
+
+// Options: ["always"]
+type X = { foo   ?: string }
+// Message: There must be a space before "foo" type annotation colon.
+
+// Options: ["always"]
+type X = { +foo: string }
+// Message: There must be a space before "foo" type annotation colon.
+
+// Options: ["always"]
+type X = { +foo  : string }
+// Message: There must be 1 space before "foo" type annotation colon.
+
+// Options: ["never"]
+type X = { +foo : string }
+// Message: There must be no space before "foo" type annotation colon.
+
+// Options: ["always"]
+type X = { +foo?: string }
+// Message: There must be a space before "foo" type annotation colon.
+
+// Options: ["always"]
+type X = { +foo?  : string }
+// Message: There must be 1 space before "foo" type annotation colon.
+
+// Options: ["never"]
+type X = { +foo? : string }
+// Message: There must be no space before "foo" type annotation colon.
+
+// Options: ["always"]
+type X = { [a: b] : c }
+// Message: There must be a space before type annotation colon.
+
+// Options: ["never"]
+type X = { [a : b]: c }
+// Message: There must be no space before type annotation colon.
+
+// Options: ["always"]
+type X = { [a  : b] : c }
+// Message: There must be 1 space before type annotation colon.
+
+// Options: ["always"]
+type X = { +[a:b] : c }
+// Message: There must be a space before type annotation colon.
+
+// Options: ["never"]
+type X = { +[a : b]: c }
+// Message: There must be no space before type annotation colon.
+
+// Options: ["always"]
+type X = { +[a  : b] : c }
+// Message: There must be 1 space before type annotation colon.
+
+// Options: ["always"]
+type X = { [a : b]: c }
+// Message: There must be a space before type annotation colon.
+
+// Options: ["never"]
+type X = { [a: b] : c }
+// Message: There must be no space before type annotation colon.
+
+// Options: ["always"]
+type X = { [a : b]  : c }
+// Message: There must be 1 space before type annotation colon.
+
+// Options: ["always"]
+type X = { [a:b]:c }
+// Message: There must be a space before type annotation colon.
+// Message: There must be a space before type annotation colon.
+
+// Options: ["never"]
+type X = { [a : b] : c }
+// Message: There must be no space before type annotation colon.
+// Message: There must be no space before type annotation colon.
+
+// Options: ["always"]
+type X = { [a  : b]  : c }
+// Message: There must be 1 space before type annotation colon.
+// Message: There must be 1 space before type annotation colon.
+
+// Options: ["always"]
+type X = { [a:(b)]:(c) }
+// Message: There must be a space before type annotation colon.
+// Message: There must be a space before type annotation colon.
+
+// Options: ["never"]
+type X = { [a : (b)] : (c) }
+// Message: There must be no space before type annotation colon.
+// Message: There must be no space before type annotation colon.
+
+// Options: ["never"]
+const x = ({} :{})
+// Message: There must be no space before type cast colon.
+
+// Options: ["always"]
+const x = ({}:{})
+// Message: There must be a space before type cast colon.
+
+// Options: ["always"]
+const x = ({}  :{})
+// Message: There must be 1 space before type cast colon.
+
+// Options: ["never"]
+((x) : string)
+// Message: There must be no space before type cast colon.
+
+// Options: ["always"]
+((x): string)
+// Message: There must be a space before type cast colon.
+
+// Options: ["always"]
+((x)  : string)
+// Message: There must be 1 space before type cast colon.
+```
+
+The following patterns are not considered problems:
+
+```js
+(foo) => {}
+
+(foo: string) => {}
+
+(foo?: string) => {}
+
+(foo ?: string) => {}
+
+// Options: ["never"]
+(foo: string) => {}
+
+// Options: ["always"]
+(foo : string) => {}
+
+// Options: ["always"]
+(foo? : string) => {}
+
+// Options: ["always"]
+(foo ? : string) => {}
+
+// Options: ["always"]
+(foo  ? : string) => {}
+
+({ lorem, ipsum, dolor }: SomeType) => {}
+
+(foo: { a: string, b: number }) => {}
+
+({ a, b }: ?{ a: string, b: number }) => {}
+
+(): { a: number, b: string } => {}
+
+// Options: ["always"]
+() : { a : number, b : string } => {}
+
+([ a, b ]: string[]) => {}
+
+(): x => {}
+
+// Options: ["always"]
+() : x => {}
+
+(): (number | string) => {}
+
+// Options: ["always"]
+() : (number | string) => {}
+
+function x(foo: string) {}
+
+// Options: ["always"]
+function x(foo : string) {}
+
+var x = function (foo: string) {}
+
+// Options: ["always"]
+var x = function (foo : string) {}
+
+class X { foo({ bar }: Props = this.props) {} }
+
+class Foo { constructor(foo: string ) {} }
+
+// Options: ["always"]
+class Foo { constructor(foo : string ) {} }
+
+async function foo({ lorem, ipsum, dolor }: SomeType) {}
+
+function x({ a, b }: { a: string, b: number }) {}
+
+function a(): x {}
+
+// Options: ["always"]
+function a() : x {}
+
+function a(): (number | string) {}
+
+// Options: ["always"]
+function a() : (number | string) {}
+
+type X = (foo:string) => number;
+
+type X = (foo: string) => number;
+
+type X = (foo: ?string) => number;
+
+type X = (foo?: string) => number;
+
+type X = (foo?: ?string) => number;
+
+type X = (foo   ?: string) => number;
+
+// Options: ["always"]
+type X = (foo? : string) => number
+
+// Options: ["always"]
+type X = (foo? : ?string) => number
+
+class Foo { bar }
+
+class Foo { bar = 3 }
+
+class Foo { bar: string }
+
+class Foo { bar: ?string }
+
+class Foo { bar:?string }
+
+// Options: ["always"]
+class Foo { bar : string }
+
+class X { static foo:number }
+
+class X { static foo: number }
+
+// Options: ["always"]
+class X { static foo :number }
+
+// Options: ["always"]
+class X { static foo : number }
+
+declare class Foo { static bar:number; }
+
+// Options: ["always"]
+declare class Foo { static bar :number; }
+
+declare class Foo { static bar: number; }
+
+// Options: ["always"]
+declare class Foo { static bar : number; }
+
+class X { +foo: string }
+
+class X { static +foo: string }
+
+// Options: ["always"]
+class X { +foo : string }
+
+// Options: ["always"]
+class X { static +foo : string }
+
+type X = { foo: string }
+
+// Options: ["always"]
+type X = { foo : string }
+
+type X = { foo?: string }
+
+type X = { foo   ?: string }
+
+// Options: ["always"]
+type X = { foo? : string }
+
+type X = { +foo: string }
+
+type X = { +foo?: string }
+
+// Options: ["always"]
+type X = { +foo : string }
+
+// Options: ["always"]
+type X = { +foo? : string }
+
+// Options: ["always"]
+type X = { [a : b] : c }
+
+// Options: ["never"]
+type X = { [a:b]:c }
+
+// Options: ["always"]
+type X = { +[a : b] : c }
+
+// Options: ["never"]
+type X = { +[a:b]:c }
+
+// Options: ["always"]
+type X = { [a : (b)] : (c) }
+
+// Options: ["never"]
+type X = { [a:(b)]:(c) }
+
+// Options: ["never"]
+const x = ({}:{})
+
+// Options: ["always"]
+const x = ({} :{})
+
+// Options: ["never"]
+((x): string)
+
+// Options: ["always"]
+((x) : string)
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-type-id-match"></a>
+### <code>type-id-match</code>
+
+Enforces a consistent naming pattern for type aliases.
+
+<a name="eslint-plugin-flowtype-rules-type-id-match-options"></a>
+#### Options
+
+This rule needs a text RegExp to operate with Its signature is as follows:
+
+```js
+{
+    "rules": {
+        "flowtype/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
+type foo = {};
+// Message: Type identifier 'foo' does not match pattern '/^([A-Z][a-z0-9]*)+Type$/'.
+
+// Options: ["^foo$"]
+type FooType = {};
+// Message: Type identifier 'FooType' does not match pattern '/^foo$/'.
+```
+
+The following patterns are not considered problems:
+
+```js
+type FooType = {};
+
+// Options: ["^foo$"]
+type foo = {};
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-union-intersection-spacing"></a>
+### <code>union-intersection-spacing</code>
+
+_The `--fix` option on the command line automatically fixes problems reported by this rule._
+
+Enforces consistent spacing around union and intersection type separators (`|` and `&`).
+
+This rule takes one argument. If it is `'always'` then a problem is raised when there is no space around the separator. If it is `'never'` then a problem is raised when there is a space around the separator.
+
+The default value is `'always'`.
+
+The following patterns are considered problems:
+
+```js
+type X = string| number;
+// Message: There must be a space before union type annotation separator
+
+// Options: ["always"]
+type X = string| number;
+// Message: There must be a space before union type annotation separator
+
+type X = string |number;
+// Message: There must be a space after union type annotation separator
+
+type X = string|number;
+// Message: There must be a space before union type annotation separator
+// Message: There must be a space after union type annotation separator
+
+type X = {x: string}|{y: number};
+// Message: There must be a space before union type annotation separator
+// Message: There must be a space after union type annotation separator
+
+type X = string | number |boolean;
+// Message: There must be a space after union type annotation separator
+
+type X = string|number|boolean;
+// Message: There must be a space before union type annotation separator
+// Message: There must be a space after union type annotation separator
+// Message: There must be a space before union type annotation separator
+// Message: There must be a space after union type annotation separator
+
+type X = (string)| number;
+// Message: There must be a space before union type annotation separator
+
+type X = ((string))|(number | foo);
+// Message: There must be a space before union type annotation separator
+// Message: There must be a space after union type annotation separator
+
+// Options: ["never"]
+type X = string |number;
+// Message: There must be no space before union type annotation separator
+
+// Options: ["never"]
+type X = string| number;
+// Message: There must be no space after union type annotation separator
+
+type X = string& number;
+// Message: There must be a space before intersection type annotation separator
+
+// Options: ["always"]
+type X = string& number;
+// Message: There must be a space before intersection type annotation separator
+
+type X = string &number;
+// Message: There must be a space after intersection type annotation separator
+
+type X = {x: string}&{y: number};
+// Message: There must be a space before intersection type annotation separator
+// Message: There must be a space after intersection type annotation separator
+
+type X = string&number;
+// Message: There must be a space before intersection type annotation separator
+// Message: There must be a space after intersection type annotation separator
+
+type X = string & number &boolean;
+// Message: There must be a space after intersection type annotation separator
+
+type X = string&number&boolean;
+// Message: There must be a space before intersection type annotation separator
+// Message: There must be a space after intersection type annotation separator
+// Message: There must be a space before intersection type annotation separator
+// Message: There must be a space after intersection type annotation separator
+
+type X = (string)& number;
+// Message: There must be a space before intersection type annotation separator
+
+type X = ((string))&(number & foo);
+// Message: There must be a space before intersection type annotation separator
+// Message: There must be a space after intersection type annotation separator
+
+// Options: ["never"]
+type X = string &number;
+// Message: There must be no space before intersection type annotation separator
+
+// Options: ["never"]
+type X = string& number;
+// Message: There must be no space after intersection type annotation separator
+```
+
+The following patterns are not considered problems:
+
+```js
+type X = string | number;
+
+type X = string | number | boolean;
+
+type X = (string) | number;
+
+type X = ((string)) | (number | foo);
+
+// Options: ["never"]
+type X = string|number
+
+type X =
+| string
+| number
+
+function x() {
+type X =
+| string
+| number
+}
+
+type X = string & number;
+
+type X = string & number & boolean;
+
+type X = (string) & number;
+
+type X = ((string)) & (number & foo);
+
+// Options: ["never"]
+type X = string&number
+
+type X =
+& string
+& number
+
+function x() {
+type X =
+& string
+& number
+}
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-use-flow-type"></a>
+### <code>use-flow-type</code>
+
+Marks Flow [type alias](https://flowtype.org/docs/type-aliases.html) declarations as used.
+
+Used to suppress [`no-unused-vars`](http://eslint.org/docs/rules/no-unused-vars) errors that are triggered by type aliases.
+
+The following patterns are not considered problems:
+
+```js
+declare class A {}
+// Additional rules: {"no-unused-vars":1}
+
+declare function A(): Y
+// Additional rules: {"no-unused-vars":1}
+
+declare module A {}
+// Additional rules: {"no-unused-vars":1}
+
+declare module A { declare var a: Y }
+// Additional rules: {"no-unused-vars":1}
+
+declare var A: Y
+// Additional rules: {"no-unused-vars":1}
+
+import type A from "a"; (function<T: A>(): T {})
+// Additional rules: {"no-unused-vars":1}
+
+(function<T: A>(): T {}); import type A from "a"
+// Additional rules: {"no-unused-vars":1}
+
+import type {A} from "a"; (function<T: A>(): T {})
+// Additional rules: {"no-unused-vars":1}
+
+(function<T: A>(): T {}); import type {A} from "a"
+// Additional rules: {"no-unused-vars":1}
+
+(function<T: A>(): T {}); import type {a as A} from "a"
+// Additional rules: {"no-unused-vars":1}
+
+type A = {}; function x<Y: A>(i: Y) { i }; x()
+// Additional rules: {"no-unused-vars":1}
+
+function x<Y: A>(i: Y) { i }; type A = {}; x()
+// Additional rules: {"no-unused-vars":1}
+
+type A = {}; function x<Y: A.B.C>(i: Y) { i }; x()
+// Additional rules: {"no-unused-vars":1}
+
+function x<Y: A.B.C>(i: Y) { i }; type A = {}; x()
+// Additional rules: {"no-unused-vars":1}
+```
+
+
+
+<a name="eslint-plugin-flowtype-rules-valid-syntax"></a>
+### <code>valid-syntax</code>
+
+**Deprecated** Babylon (the Babel parser) v6.10.0 fixes parsing of the invalid syntax this plugin warned against.
+
+Checks for simple Flow syntax errors.
+
diff --git a/bin/readmeAssertions.js b/bin/readmeAssertions.js
new file mode 100644
index 0000000..4b96260
--- /dev/null
+++ b/bin/readmeAssertions.js
@@ -0,0 +1,84 @@
+/**
+ * This script is used to inline assertions into the README.md documents.
+ */
+import _ from 'lodash';
+import glob from 'glob';
+import path from 'path';
+import fs from 'fs';
+
+const formatCodeSnippet = (setup) => {
+    const paragraphs = [];
+
+    if (setup.options) {
+        paragraphs.push('// Options: ' + JSON.stringify(setup.options));
+    }
+
+    paragraphs.push(setup.code);
+
+    if (setup.errors) {
+        setup.errors.forEach((message) => {
+            paragraphs.push('// Message: ' + message.message);
+        });
+    }
+
+    if (setup.rules) {
+        paragraphs.push('// Additional rules: ' + JSON.stringify(setup.rules));
+    }
+
+    return paragraphs.join('\n');
+};
+
+const getAssertions = () => {
+    const assertionFiles = glob.sync(path.resolve(__dirname, './../tests/rules/assertions/*.js'));
+
+    const assertionNames = _.map(assertionFiles, (filePath) => {
+        return path.basename(filePath, '.js');
+    });
+
+    const assertionCodes = _.map(assertionFiles, (filePath) => {
+        const codes = require(filePath);
+
+        return {
+            valid: _.map(codes.valid, formatCodeSnippet),
+            invalid: _.map(codes.invalid, formatCodeSnippet)
+        };
+    });
+
+    return _.zipObject(assertionNames, assertionCodes);
+};
+
+const updateDocuments = (assertions) => {
+    const readmeDocumentPath = path.join(__dirname, './../README.md');
+
+    let documentBody = fs.readFileSync(readmeDocumentPath, 'utf8');
+
+    documentBody = documentBody.replace(/<!-- assertions ([a-z]+?) -->/ig, (assertionsBlock) => {
+        let exampleBody;
+
+        const ruleName = assertionsBlock.match(/assertions ([a-z]+)/i)[1];
+
+        const ruleAssertions = assertions[ruleName];
+
+        if (!ruleAssertions) {
+            throw new Error('No assertions available for rule "' + ruleName + '".');
+
+            return assertionsBlock;
+        }
+
+        exampleBody = '';
+
+        if (ruleAssertions.invalid.length) {
+            exampleBody += 'The following patterns are considered problems:\n\n```js\n' + ruleAssertions.invalid.join('\n\n') + '\n```\n\n';
+        }
+
+        if (ruleAssertions.valid.length) {
+            exampleBody += 'The following patterns are not considered problems:\n\n```js\n' + ruleAssertions.valid.join('\n\n') + '\n```\n\n';
+        }
+
+        return exampleBody;
+    });
+
+    fs.writeFileSync(readmeDocumentPath, documentBody);
+};
+
+updateDocuments(getAssertions());
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..3447415
--- /dev/null
+++ b/package.json
@@ -0,0 +1,57 @@
+{
+  "name": "eslint-plugin-flowtype",
+  "description": "Flowtype linting rules for ESLint.",
+  "version": "2.25.0",
+  "main": "./dist/index.js",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/gajus/eslint-plugin-flowtype"
+  },
+  "keywords": [
+    "eslint",
+    "plugin",
+    "flowtype"
+  ],
+  "author": {
+    "name": "Gajus Kuizinas",
+    "email": "gajus at gajus.com",
+    "url": "http://gajus.com"
+  },
+  "license": "BSD-3-Clause",
+  "peerDependencies": {
+    "eslint": ">=2.0.0"
+  },
+  "dependencies": {
+    "lodash": "^4.15.0"
+  },
+  "scripts": {
+    "lint": "eslint ./src ./tests",
+    "test": "mocha --compilers js:babel-register ./tests/rules/index.js",
+    "build": "babel ./src --out-dir ./dist --copy-files",
+    "documentation-add-assertions": "babel-node ./bin/readmeAssertions",
+    "documentation": "gitdown ./.README/README.md --output-file ./README.md; npm run documentation-add-assertions",
+    "create-index": "create-index ./src --update-index",
+    "precommit": "npm run lint && npm run test && npm run format-json",
+    "commitmsg": "conventional-changelog-lint -e",
+    "format-json": "jsonlint --sort-keys --in-place --indent '  ' ./src/configs/recommended.json && echo '' >> ./src/configs/recommended.json"
+  },
+  "devDependencies": {
+    "babel-cli": "^6.14.0",
+    "babel-eslint": "^6.1.2",
+    "babel-plugin-add-module-exports": "^0.2.1",
+    "babel-preset-es2015": "^6.14.0",
+    "babel-preset-stage-0": "^6.5.0",
+    "babel-register": "^6.14.0",
+    "chai": "^3.5.0",
+    "conventional-changelog-lint": "^1.0.1",
+    "create-index": "^0.1.3",
+    "eslint": "^3.4.0",
+    "eslint-config-canonical": "1.8.1",
+    "gitdown": "^2.5.0",
+    "husky": "^0.11.7",
+    "jsonlint": "^1.6.2",
+    "mocha": "^3.0.2",
+    "standard-version": "^2.4.0",
+    "travis-after-all": "^1.4.4"
+  }
+}
diff --git a/src/configs/recommended.json b/src/configs/recommended.json
new file mode 100644
index 0000000..dc14900
--- /dev/null
+++ b/src/configs/recommended.json
@@ -0,0 +1,44 @@
+{
+  "parser": "babel-eslint",
+  "rules": {
+    "flowtype/boolean-style": [
+      2,
+      "boolean"
+    ],
+    "flowtype/define-flow-type": 1,
+    "flowtype/delimiter-dangle": 0,
+    "flowtype/generic-spacing": [
+      2,
+      "never"
+    ],
+    "flowtype/no-weak-types": 0,
+    "flowtype/require-parameter-type": 0,
+    "flowtype/require-return-type": 0,
+    "flowtype/require-valid-file-annotation": 0,
+    "flowtype/semi": 0,
+    "flowtype/space-after-type-colon": [
+      2,
+      "always"
+    ],
+    "flowtype/space-before-generic-bracket": [
+      2,
+      "never"
+    ],
+    "flowtype/space-before-type-colon": [
+      2,
+      "never"
+    ],
+    "flowtype/type-id-match": 0,
+    "flowtype/union-intersection-spacing": [
+      2,
+      "always"
+    ],
+    "flowtype/use-flow-type": 1,
+    "flowtype/valid-syntax": 1
+  },
+  "settings": {
+    "flowtype": {
+      "onlyFilesWithFlowAnnotation": false
+    }
+  }
+}
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..0bae069
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,67 @@
+import defineFlowType from './rules/defineFlowType';
+import genericSpacing from './rules/genericSpacing';
+import noWeakTypes from './rules/noWeakTypes';
+import requireParameterType from './rules/requireParameterType';
+import requireReturnType from './rules/requireReturnType';
+import requireValidFileAnnotation from './rules/requireValidFileAnnotation';
+import semi from './rules/semi';
+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 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 sortKeys from './rules/sortKeys';
+import objectTypeDelimiter from './rules/objectTypeDelimiter';
+import recommended from './configs/recommended.json';
+
+export default {
+  configs: {
+    recommended
+  },
+  rules: {
+    'boolean-style': booleanStyle,
+    'define-flow-type': defineFlowType,
+    'delimiter-dangle': delimiterDangle,
+    'generic-spacing': genericSpacing,
+    'no-dupe-keys': noDupeKeys,
+    'no-weak-types': noWeakTypes,
+    'object-type-delimiter': objectTypeDelimiter,
+    'require-parameter-type': requireParameterType,
+    'require-return-type': requireReturnType,
+    'require-valid-file-annotation': requireValidFileAnnotation,
+    semi,
+    'sort-keys': sortKeys,
+    'space-after-type-colon': spaceAfterTypeColon,
+    'space-before-generic-bracket': spaceBeforeGenericBracket,
+    'space-before-type-colon': spaceBeforeTypeColon,
+    'type-id-match': typeIdMatch,
+    'union-intersection-spacing': unionIntersectionSpacing,
+    'use-flow-type': useFlowType,
+    'valid-syntax': validSyntax
+  },
+  rulesConfig: {
+    'boolean-style': 0,
+    'define-flow-type': 0,
+    'delimiter-dangle': 0,
+    'generic-spacing': 0,
+    'no-dupe-keys': 0,
+    'no-weak-types': 0,
+    'object-type-delimiter': 0,
+    'require-parameter-type': 0,
+    'require-return-type': 0,
+    semi: 0,
+    'sort-keys': 0,
+    'space-after-type-colon': 0,
+    'space-before-generic-bracket': 0,
+    'space-before-type-colon': 0,
+    'type-id-match': 0,
+    'union-intersection-spacing': 0,
+    'use-flow-type': 0,
+    'valid-syntax': 0
+  }
+};
diff --git a/src/rules/booleanStyle.js b/src/rules/booleanStyle.js
new file mode 100644
index 0000000..9ddad7b
--- /dev/null
+++ b/src/rules/booleanStyle.js
@@ -0,0 +1,29 @@
+export default (context) => {
+  const longForm = (context.options[0] || 'boolean') === 'boolean';
+
+  return {
+    BooleanTypeAnnotation (node) {
+      const diff = node.end - node.start;
+
+      if (longForm && diff === 4) {
+        context.report({
+          fix (fixer) {
+            return fixer.replaceText(node, 'boolean');
+          },
+          message: 'Use "boolean", not "bool"',
+          node
+        });
+      }
+
+      if (!longForm && diff !== 4) {
+        context.report({
+          fix (fixer) {
+            return fixer.replaceText(node, 'bool');
+          },
+          message: 'Use "bool", not "boolean"',
+          node
+        });
+      }
+    }
+  };
+};
diff --git a/src/rules/defineFlowType.js b/src/rules/defineFlowType.js
new file mode 100644
index 0000000..27e76a5
--- /dev/null
+++ b/src/rules/defineFlowType.js
@@ -0,0 +1,64 @@
+export const schema = [];
+
+export default (context) => {
+  let globalScope;
+
+    // do nearly the same thing that eslint does for config globals
+    // https://github.com/eslint/eslint/blob/v2.0.0/lib/eslint.js#L118-L194
+  const makeDefined = (ident) => {
+    let ii;
+
+        // start from the right since we're going to remove items from the array
+    for (ii = globalScope.through.length - 1; ii >= 0; ii--) {
+      const ref = globalScope.through[ii];
+
+      if (ref.identifier.name === ident.name) {
+                // use "__defineGeneric" since we don't have a reference to "escope.Variable"
+        globalScope.__defineGeneric( // eslint-disable-line no-underscore-dangle
+                    ident.name,
+                    globalScope.set,
+                    globalScope.variables
+                );
+        const variable = globalScope.set.get(ident.name);
+
+        variable.writeable = false;
+                // "through" contains all references whose definition cannot be found
+                // so we need to update references and remove the ones that were added
+        globalScope.through.splice(ii, 1);
+        ref.resolved = variable;
+        variable.references.push(ref);
+      }
+    }
+  };
+
+  return {
+    ClassImplements (node) {
+      makeDefined(node.id);
+    },
+    GenericTypeAnnotation (node) {
+      if (node.id.type === 'Identifier') {
+        makeDefined(node.id);
+      } else if (node.id.type === 'QualifiedTypeIdentifier') {
+        let qid;
+
+        qid = node.id;
+        do {
+          qid = qid.qualification;
+        } while (qid.qualification);
+
+        makeDefined(qid);
+      }
+    },
+    InterfaceDeclaration (node) {
+      makeDefined(node.id);
+    },
+    Program () {
+      globalScope = context.getScope();
+    },
+    TypeParameterDeclaration (node) {
+      node.params.forEach((param) => {
+        makeDefined(param);
+      });
+    }
+  };
+};
diff --git a/src/rules/delimiterDangle.js b/src/rules/delimiterDangle.js
new file mode 100644
index 0000000..a71cd7b
--- /dev/null
+++ b/src/rules/delimiterDangle.js
@@ -0,0 +1,105 @@
+import _ from 'lodash';
+
+export default (context) => {
+  const option = context.options[0] || 'never';
+  const sourceCode = context.getSourceCode();
+
+  const reporter = (node, message, fix) => {
+    return () => {
+      context.report({
+        fix,
+        message,
+        node
+      });
+    };
+  };
+
+  const makeReporters = (node, tokenToFix) => {
+    return {
+      dangle: reporter(node, 'Unexpected trailing delimiter', (fixer) => {
+        return fixer.replaceText(tokenToFix, '');
+      }),
+      noDangle: reporter(node, 'Missing trailing delimiter', (fixer) => {
+        return fixer.insertTextAfter(tokenToFix, ',');
+      })
+    };
+  };
+
+  const evaluate = (node, lastChildNode) => {
+    if (!lastChildNode) {
+      return;
+    }
+
+    const [penultimateToken, lastToken] = sourceCode.getLastTokens(node, 2);
+
+    const isDangling = [';', ','].indexOf(penultimateToken.value) > -1;
+    const isMultiLine = penultimateToken.loc.start.line !== lastToken.loc.start.line;
+
+    const report = makeReporters(lastChildNode, penultimateToken);
+
+    if (option === 'always' && !isDangling) {
+      report.noDangle();
+
+      return;
+    }
+
+    if (option === 'never' && isDangling) {
+      report.dangle();
+
+      return;
+    }
+
+    if (option === 'always-multiline' && !isDangling && isMultiLine) {
+      report.noDangle();
+
+      return;
+    }
+
+    if (option === 'always-multiline' && isDangling && !isMultiLine) {
+      report.dangle();
+
+      return;
+    }
+
+    if (option === 'only-multiline' && isDangling && !isMultiLine) {
+      report.dangle();
+
+      return;
+    }
+  };
+
+  // required for reporting the correct position
+  const getLast = (property, indexer) => {
+    if (!property) {
+      return indexer;
+    }
+
+    if (!indexer) {
+      return property;
+    }
+
+    if (property.loc.end.line > indexer.loc.end.line) {
+      return property;
+    }
+
+    if (indexer.loc.end.line > property.loc.end.line) {
+      return indexer;
+    }
+
+    if (property.loc.end.column > indexer.loc.end.column) {
+      return property;
+    }
+
+    return indexer;
+  };
+
+  return {
+    ObjectTypeAnnotation (node) {
+      evaluate(node, getLast(_.last(node.properties), _.last(node.indexers)));
+    },
+
+    TupleTypeAnnotation (node) {
+      evaluate(node, _.last(node.types));
+    }
+  };
+};
diff --git a/src/rules/genericSpacing.js b/src/rules/genericSpacing.js
new file mode 100644
index 0000000..e438e4f
--- /dev/null
+++ b/src/rules/genericSpacing.js
@@ -0,0 +1,78 @@
+import {spacingFixers} from './../utilities';
+
+export default (context) => {
+  const sourceCode = context.getSourceCode();
+
+  const never = (context.options[0] || 'never') === 'never';
+
+  return {
+    GenericTypeAnnotation (node) {
+      const types = node.typeParameters;
+
+            // Promise<foo>
+            // ^^^^^^^^^^^^ GenericTypeAnnotation (with typeParameters)
+            //         ^^^  GenericTypeAnnotation (without typeParameters)
+      if (!types) {
+        return;
+      }
+
+      const [opener, firstInnerToken] = sourceCode.getFirstTokens(types, 2);
+      const [lastInnerToken, closer] = sourceCode.getLastTokens(types, 2);
+
+      const spacesBefore = firstInnerToken.start - opener.end;
+      const spacesAfter = closer.start - lastInnerToken.end;
+
+      if (never) {
+        if (spacesBefore) {
+          context.report({
+            data: {name: node.id.name},
+            fix: spacingFixers.stripSpacesAfter(opener, spacesBefore),
+            message: 'There must be no space at start of "{{name}}" generic type annotation',
+            node: types
+          });
+        }
+
+        if (spacesAfter) {
+          context.report({
+            data: {name: node.id.name},
+            fix: spacingFixers.stripSpacesAfter(lastInnerToken, spacesAfter),
+            message: 'There must be no space at end of "{{name}}" generic type annotation',
+            node: types
+          });
+        }
+      } else {
+        if (spacesBefore > 1) {
+          context.report({
+            data: {name: node.id.name},
+            fix: spacingFixers.stripSpacesAfter(opener, spacesBefore - 1),
+            message: 'There must be one space at start of "{{name}}" generic type annotation',
+            node: types
+          });
+        } else if (spacesBefore === 0) {
+          context.report({
+            data: {name: node.id.name},
+            fix: spacingFixers.addSpaceAfter(opener),
+            message: 'There must be a space at start of "{{name}}" generic type annotation',
+            node: types
+          });
+        }
+
+        if (spacesAfter > 1) {
+          context.report({
+            data: {name: node.id.name},
+            fix: spacingFixers.stripSpacesAfter(lastInnerToken, spacesAfter - 1),
+            message: 'There must be one space at end of "{{name}}" generic type annotation',
+            node: types
+          });
+        } else if (spacesAfter === 0) {
+          context.report({
+            data: {name: node.id.name},
+            fix: spacingFixers.addSpaceAfter(lastInnerToken),
+            message: 'There must be a space at end of "{{name}}" generic type annotation',
+            node: types
+          });
+        }
+      }
+    }
+  };
+};
diff --git a/src/rules/noDupeKeys.js b/src/rules/noDupeKeys.js
new file mode 100644
index 0000000..d419b2f
--- /dev/null
+++ b/src/rules/noDupeKeys.js
@@ -0,0 +1,32 @@
+import _ from 'lodash/';
+import {
+  getParameterName
+} from './../utilities';
+
+export default (context) => {
+  const report = (node) => {
+    context.report({
+      loc: node.loc,
+      message: 'Duplicate property.',
+      node
+    });
+  };
+
+  const checkForDuplicates = (node) => {
+    const haystack = [];
+
+    _.forEach(node.properties, (identifierNode) => {
+      const needle = getParameterName(identifierNode, context);
+
+      if (_.includes(haystack, needle)) {
+        report(identifierNode);
+      } else {
+        haystack.push(needle);
+      }
+    });
+  };
+
+  return {
+    ObjectTypeAnnotation: checkForDuplicates
+  };
+};
diff --git a/src/rules/noWeakTypes.js b/src/rules/noWeakTypes.js
new file mode 100644
index 0000000..bc99608
--- /dev/null
+++ b/src/rules/noWeakTypes.js
@@ -0,0 +1,42 @@
+import _ from 'lodash';
+
+const reportWeakType = (context, weakType) => {
+  return (node) => {
+    context.report({
+      data: {weakType},
+      message: 'Unexpected use of weak type "{{weakType}}"',
+      node
+    });
+  };
+};
+
+const genericTypeEvaluator = (context, {checkFunction, checkObject}) => {
+  return (node) => {
+    const name = _.get(node, 'id.name');
+
+    if (checkFunction && name === 'Function' || checkObject && name === 'Object') {
+      reportWeakType(context, name)(node);
+    }
+  };
+};
+
+export default (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;
+
+  const checks = {};
+
+  if (checkAny) {
+    checks.AnyTypeAnnotation = reportWeakType(context, 'any');
+  }
+
+  if (checkFunction || checkObject) {
+    checks.GenericTypeAnnotation = genericTypeEvaluator(context, {
+      checkFunction,
+      checkObject
+    });
+  }
+
+  return checks;
+};
diff --git a/src/rules/objectTypeDelimiter.js b/src/rules/objectTypeDelimiter.js
new file mode 100644
index 0000000..d6265f0
--- /dev/null
+++ b/src/rules/objectTypeDelimiter.js
@@ -0,0 +1,59 @@
+ // ported from babel/flow-object-type; original author: Nat Mote
+ // https://github.com/babel/eslint-plugin-babel/blob/c0a49d25a97feb12c1d07073a0b37317359a5fe5/rules/flow-object-type.js
+
+const SEMICOLON = {
+  char: ';',
+  name: 'semicolon'
+};
+
+const COMMA = {
+  char: ',',
+  name: 'comma'
+};
+
+const create = (context) => {
+  let GOOD;
+  let BAD;
+
+  if (!context.options[0] || context.options[0] === COMMA.name) {
+    GOOD = COMMA;
+    BAD = SEMICOLON;
+  } else {
+    GOOD = SEMICOLON;
+    BAD = COMMA;
+  }
+
+  const requireProperPunctuation = (node) => {
+    const tokens = context.getSourceCode().getTokens(node);
+    const lastToken = tokens[tokens.length - 1];
+
+    if (lastToken.type === 'Punctuator') {
+      if (lastToken.value === BAD.char) {
+        context.report({
+          fix (fixer) {
+            return fixer.replaceText(lastToken, GOOD.char);
+          },
+          message: 'Prefer ' + GOOD.name + 's to ' + BAD.name + 's in object and class types',
+          node: lastToken
+        });
+      }
+    }
+  };
+
+  return {
+    ObjectTypeCallProperty: requireProperPunctuation,
+    ObjectTypeIndexer: requireProperPunctuation,
+    ObjectTypeProperty: requireProperPunctuation
+  };
+};
+
+const schema = [
+  {
+    enum: ['semicolon', 'comma']
+  }
+];
+
+export default {
+  create,
+  schema
+};
diff --git a/src/rules/requireParameterType.js b/src/rules/requireParameterType.js
new file mode 100644
index 0000000..5a7e2ce
--- /dev/null
+++ b/src/rules/requireParameterType.js
@@ -0,0 +1,47 @@
+import _ from 'lodash';
+import {
+    getParameterName,
+    isFlowFile,
+    iterateFunctionNodes,
+    quoteName
+} from './../utilities';
+
+export default iterateFunctionNodes((context) => {
+  const checkThisFile = !_.get(context, 'settings.flowtype.onlyFilesWithFlowAnnotation') || isFlowFile(context);
+
+  if (!checkThisFile) {
+    return () => {};
+  }
+
+  const skipArrows = _.get(context, 'options[0].excludeArrowFunctions');
+  const excludeParameterMatch = new RegExp(_.get(context, 'options[0].excludeParameterMatch', 'a^'));
+
+  return (functionNode) => {
+    _.forEach(functionNode.params, (identifierNode) => {
+      const parameterName = getParameterName(identifierNode, context);
+
+      if (excludeParameterMatch.test(parameterName)) {
+        return;
+      }
+
+      const typeAnnotation = _.get(identifierNode, 'typeAnnotation') || _.get(identifierNode, 'left.typeAnnotation');
+
+      const isArrow = functionNode.type === 'ArrowFunctionExpression';
+      const isArrowFunctionExpression = functionNode.expression;
+
+      if (skipArrows === 'expressionsOnly' && isArrowFunctionExpression || skipArrows === true && isArrow) {
+        return;
+      }
+
+      if (!typeAnnotation) {
+        context.report({
+          data: {
+            name: quoteName(parameterName)
+          },
+          message: 'Missing {{name}}parameter type annotation.',
+          node: identifierNode
+        });
+      }
+    });
+  };
+});
diff --git a/src/rules/requireReturnType.js b/src/rules/requireReturnType.js
new file mode 100644
index 0000000..47b255f
--- /dev/null
+++ b/src/rules/requireReturnType.js
@@ -0,0 +1,83 @@
+import _ from 'lodash';
+import {
+    isFlowFile
+} from './../utilities';
+
+export default (context) => {
+  const checkThisFile = !_.get(context, 'settings.flowtype.onlyFilesWithFlowAnnotation') || isFlowFile(context);
+
+  if (!checkThisFile) {
+    return () => {};
+  }
+
+  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;
+
+  const targetNodes = [];
+
+  const registerFunction = (functionNode) => {
+    targetNodes.push({
+      functionNode
+    });
+  };
+
+  const isUndefinedReturnType = (returnNode) => {
+    return returnNode.argument === null || returnNode.argument.name === 'undefined' || returnNode.argument.operator === 'void';
+  };
+
+  const getIsReturnTypeAnnotationUndefined = (targetNode) => {
+    const isReturnTypeAnnotationLiteralUndefined = _.get(targetNode, 'functionNode.returnType.typeAnnotation.id.name') === 'undefined' && _.get(targetNode, 'functionNode.returnType.typeAnnotation.type') === 'GenericTypeAnnotation';
+    const isReturnTypeAnnotationVoid = _.get(targetNode, 'functionNode.returnType.typeAnnotation.type') === 'VoidTypeAnnotation';
+
+    return isReturnTypeAnnotationLiteralUndefined || isReturnTypeAnnotationVoid;
+  };
+
+  const evaluateFunction = (functionNode) => {
+    const targetNode = targetNodes.pop();
+
+    if (functionNode !== targetNode.functionNode) {
+      throw new Error('Mismatch.');
+    }
+
+    const isArrow = functionNode.type === 'ArrowFunctionExpression';
+    const isArrowFunctionExpression = functionNode.expression;
+    const hasImplicitReturnType = functionNode.async || functionNode.generator;
+    const isFunctionReturnUndefined = !isArrowFunctionExpression && !hasImplicitReturnType && (!targetNode.returnStatementNode || isUndefinedReturnType(targetNode.returnStatementNode));
+    const isReturnTypeAnnotationUndefined = getIsReturnTypeAnnotationUndefined(targetNode);
+
+    if (skipArrows === 'expressionsOnly' && isArrowFunctionExpression || skipArrows === true && isArrow) {
+      return;
+    }
+
+    if (isFunctionReturnUndefined && isReturnTypeAnnotationUndefined && !annotateUndefined) {
+      context.report(functionNode, 'Must not annotate undefined return type.');
+    } else if (isFunctionReturnUndefined && !isReturnTypeAnnotationUndefined && annotateUndefined) {
+      context.report(functionNode, 'Must annotate undefined return type.');
+    } else if (!isFunctionReturnUndefined && !isReturnTypeAnnotationUndefined) {
+      if (annotateReturn && !functionNode.returnType) {
+        context.report(functionNode, 'Missing return type annotation.');
+      }
+    }
+  };
+
+  const evaluateNoise = () => {
+    targetNodes.pop();
+  };
+
+  return {
+    ArrowFunctionExpression: registerFunction,
+    'ArrowFunctionExpression:exit': evaluateFunction,
+    ClassDeclaration: registerFunction,
+    'ClassDeclaration:exit': evaluateNoise,
+    ClassExpression: registerFunction,
+    'ClassExpression:exit': evaluateNoise,
+    FunctionDeclaration: registerFunction,
+    'FunctionDeclaration:exit': evaluateFunction,
+    FunctionExpression: registerFunction,
+    'FunctionExpression:exit': evaluateFunction,
+    ReturnStatement: (node) => {
+      targetNodes[targetNodes.length - 1].returnStatementNode = node;
+    }
+  };
+};
diff --git a/src/rules/requireValidFileAnnotation.js b/src/rules/requireValidFileAnnotation.js
new file mode 100644
index 0000000..2087446
--- /dev/null
+++ b/src/rules/requireValidFileAnnotation.js
@@ -0,0 +1,66 @@
+import _ from 'lodash';
+import {
+    isFlowFile,
+    isFlowFileAnnotation
+} from './../utilities';
+
+const defaults = {
+  annotationStyle: 'none'
+};
+
+const looksLikeFlowFileAnnotation = (comment) => {
+  return /@(?:no)?flow/i.test(comment);
+};
+
+const isValidAnnotationStyle = (node, style) => {
+  if (style === 'none') {
+    return true;
+  }
+
+  return style === node.type.toLowerCase();
+};
+
+export const schema = [
+  {
+    enum: ['always']
+  }
+];
+
+export default (context) => {
+  const checkThisFile = !_.get(context, 'settings.flowtype.onlyFilesWithFlowAnnotation') || isFlowFile(context);
+
+  if (!checkThisFile) {
+    return {};
+  }
+
+  const always = context.options[0] === 'always';
+  const style = _.get(context, 'options[1].annotationStyle', defaults.annotationStyle);
+
+  return {
+    Program (node) {
+      const firstToken = node.tokens[0];
+
+      const potentialFlowFileAnnotation = _.find(context.getAllComments(), (comment) => {
+        return looksLikeFlowFileAnnotation(comment.value);
+      });
+
+      if (potentialFlowFileAnnotation) {
+        if (firstToken && firstToken.start < potentialFlowFileAnnotation.start) {
+          context.report(potentialFlowFileAnnotation, 'Flow file annotation not at the top of the file.');
+        }
+
+        if (!isFlowFileAnnotation(potentialFlowFileAnnotation.value)) {
+          context.report(potentialFlowFileAnnotation, 'Malformed flow file annotation.');
+        }
+
+        if (!isValidAnnotationStyle(potentialFlowFileAnnotation, style)) {
+          const str = style === 'line' ? '`// @flow`' : '`/* @flow */`';
+
+          context.report(potentialFlowFileAnnotation, 'Flow file annotation style must be ' + str);
+        }
+      } else if (always) {
+        context.report(node, 'Flow file annotation is missing.');
+      }
+    }
+  };
+};
diff --git a/src/rules/semi.js b/src/rules/semi.js
new file mode 100644
index 0000000..1dc6ddf
--- /dev/null
+++ b/src/rules/semi.js
@@ -0,0 +1,52 @@
+export default (context) => {
+  const never = (context.options[0] || 'always') === 'never';
+  const sourceCode = context.getSourceCode();
+
+  const report = (node, missing) => {
+    const lastToken = sourceCode.getLastToken(node);
+    let fix, message;
+    let {loc} = lastToken;
+
+    if (missing) {
+      message = 'Missing semicolon.';
+      loc = loc.end;
+      fix = (fixer) => {
+        return fixer.insertTextAfter(lastToken, ';');
+      };
+    } else {
+      message = 'Extra semicolon.';
+      loc = loc.start;
+      fix = (fixer) => {
+        return fixer.remove(lastToken);
+      };
+    }
+
+    context.report({
+      fix,
+      loc,
+      message,
+      node
+    });
+  };
+
+  const isSemicolon = (token) => {
+    return token.type === 'Punctuator' && token.value === ';';
+  };
+
+  const checkForSemicolon = (node) => {
+    const lastToken = sourceCode.getLastToken(node);
+    const isLastTokenSemicolon = isSemicolon(lastToken);
+
+    if (never && isLastTokenSemicolon) {
+      report(node, false);
+    }
+
+    if (!never && !isLastTokenSemicolon) {
+      report(node, true);
+    }
+  };
+
+  return {
+    TypeAlias: checkForSemicolon
+  };
+};
diff --git a/src/rules/sortKeys.js b/src/rules/sortKeys.js
new file mode 100644
index 0000000..43d2012
--- /dev/null
+++ b/src/rules/sortKeys.js
@@ -0,0 +1,91 @@
+import _ from 'lodash';
+import {
+  getParameterName
+} from './../utilities';
+
+const defaults = {
+  caseSensitive: true,
+  natural: false
+};
+
+/**
+ * Functions to compare the order of two strings
+ *
+ * Based on a similar function from eslint's sort-keys rule.
+ * https://github.com/eslint/eslint/blob/master/lib/rules/sort-keys.js
+ *
+ * @private
+ */
+const isValidOrders = {
+  asc (str1, str2) {
+    return str1 <= str2;
+  },
+  ascI (str1, str2) {
+    return str1.toLowerCase() <= str2.toLowerCase();
+  },
+  ascIN (str1, str2) {
+    return isValidOrders.naturalCompare(str1.toLowerCase(), str2.toLowerCase()) <= 0;
+  },
+  ascN (str1, str2) {
+    return isValidOrders.naturalCompare(str1, str2) <= 0;
+  },
+  desc (str1, str2) {
+    return isValidOrders.asc(str2, str1);
+  },
+  descI (str1, str2) {
+    return isValidOrders.ascI(str2, str1);
+  },
+  descIN (str1, str2) {
+    return isValidOrders.ascIN(str2, str1);
+  },
+  descN (str1, str2) {
+    return isValidOrders.ascN(str2, str1);
+  },
+  naturalCompare (str1, str2) {
+    return str1.localeCompare(str2, 'en-US', {numeric: true});
+  }
+};
+
+export default (context) => {
+  const order = _.get(context, ['options', 0], 'asc');
+  const {natural, caseSensitive} = _.get(context, ['options', 1], defaults);
+  const insensitive = caseSensitive === false;
+
+  let prev;
+  const checkKeyOrder = (node) => {
+    prev = null;
+
+    _.forEach(node.properties, (identifierNode) => {
+      const current = getParameterName(identifierNode, context);
+      const last = prev;
+
+      // keep track of the last token
+      prev = current || last;
+
+      if (!last || !current) {
+        return;
+      }
+
+      const isValidOrder = isValidOrders[order + (insensitive ? 'I' : '') + (natural ? 'N' : '')];
+
+      if (isValidOrder(last, current) === false) {
+        context.report({
+          data: {
+            current,
+            insensitive: insensitive ? 'insensitive ' : '',
+            last,
+            natural: natural ? 'natural ' : '',
+            order
+          },
+          loc: identifierNode.loc,
+          message: 'Expected type annotations to be in {{natural}}{{insensitive}}{{order}}ending order. "{{current}}" should be before "{{last}}".',
+          node: identifierNode
+        });
+      }
+    });
+  };
+
+  return {
+    ObjectTypeAnnotation: checkKeyOrder
+  };
+};
diff --git a/src/rules/spaceAfterTypeColon.js b/src/rules/spaceAfterTypeColon.js
new file mode 100644
index 0000000..d93b0c8
--- /dev/null
+++ b/src/rules/spaceAfterTypeColon.js
@@ -0,0 +1,7 @@
+import makeSpacing from './typeColonSpacing';
+
+export default (context) => {
+  return makeSpacing('after', context, {
+    always: (context.options[0] || 'always') === 'always'
+  });
+};
diff --git a/src/rules/spaceBeforeGenericBracket.js b/src/rules/spaceBeforeGenericBracket.js
new file mode 100644
index 0000000..f0902d0
--- /dev/null
+++ b/src/rules/spaceBeforeGenericBracket.js
@@ -0,0 +1,47 @@
+import {spacingFixers} from '../utilities';
+
+export default (context) => {
+  const never = (context.options[0] || 'never') === 'never';
+
+  return {
+    GenericTypeAnnotation (node) {
+      const types = node.typeParameters;
+
+            // Promise<foo>
+            // ^^^^^^^^^^^^ GenericTypeAnnotation (with typeParameters)
+            //         ^^^  GenericTypeAnnotation (without typeParameters)
+      if (!types) {
+        return;
+      }
+
+      const spaceBefore = types.start - node.id.end;
+
+      if (never && spaceBefore) {
+        context.report({
+          data: {name: node.id.name},
+          fix: spacingFixers.stripSpacesAfter(node.id, spaceBefore),
+          message: 'There must be no space before "{{name}}" generic type annotation bracket',
+          node
+        });
+      }
+
+      if (!never && !spaceBefore) {
+        context.report({
+          data: {name: node.id.name},
+          fix: spacingFixers.addSpaceAfter(node.id),
+          message: 'There must be a space before "{{name}}" generic type annotation bracket',
+          node
+        });
+      }
+
+      if (!never && spaceBefore > 1) {
+        context.report({
+          data: {name: node.id.name},
+          fix: spacingFixers.stripSpacesAfter(node.id, spaceBefore - 1),
+          message: 'There must be one space before "{{name}}" generic type annotation bracket',
+          node
+        });
+      }
+    }
+  };
+};
diff --git a/src/rules/spaceBeforeTypeColon.js b/src/rules/spaceBeforeTypeColon.js
new file mode 100644
index 0000000..b199063
--- /dev/null
+++ b/src/rules/spaceBeforeTypeColon.js
@@ -0,0 +1,7 @@
+import makeSpacing from './typeColonSpacing';
+
+export default (context) => {
+  return makeSpacing('before', context, {
+    always: context.options[0] === 'always'
+  });
+};
diff --git a/src/rules/typeColonSpacing/evaluateFunctions.js b/src/rules/typeColonSpacing/evaluateFunctions.js
new file mode 100644
index 0000000..f6ccd5a
--- /dev/null
+++ b/src/rules/typeColonSpacing/evaluateFunctions.js
@@ -0,0 +1,14 @@
+import _ from 'lodash';
+import {iterateFunctionNodes} from '../../utilities';
+import evaluateTypical from './evaluateTypical';
+import evaluateReturnType from './evaluateReturnType';
+
+export default iterateFunctionNodes((context, report) => {
+  const checkParam = evaluateTypical(context, report, 'parameter');
+  const checkReturnType = evaluateReturnType(context, report);
+
+  return (functionNode) => {
+    _.forEach(functionNode.params, checkParam);
+    checkReturnType(functionNode);
+  };
+});
diff --git a/src/rules/typeColonSpacing/evaluateObjectTypeIndexer.js b/src/rules/typeColonSpacing/evaluateObjectTypeIndexer.js
new file mode 100644
index 0000000..914be1e
--- /dev/null
+++ b/src/rules/typeColonSpacing/evaluateObjectTypeIndexer.js
@@ -0,0 +1,21 @@
+import {getTokenAfterParens, getTokenBeforeParens} from '../../utilities';
+
+export default (context, report) => {
+  const sourceCode = context.getSourceCode();
+
+  return (objectTypeIndexer) => {
+    // type X = { [a: b]: c }
+    //              ^
+    report({
+      colon: getTokenBeforeParens(sourceCode, objectTypeIndexer.key),
+      node: objectTypeIndexer
+    });
+
+    // type X = { [a: b]: c }
+    //                  ^
+    report({
+      colon: sourceCode.getTokenAfter(getTokenAfterParens(sourceCode, objectTypeIndexer.key)),
+      node: objectTypeIndexer
+    });
+  };
+};
diff --git a/src/rules/typeColonSpacing/evaluateObjectTypeProperty.js b/src/rules/typeColonSpacing/evaluateObjectTypeProperty.js
new file mode 100644
index 0000000..44af4f8
--- /dev/null
+++ b/src/rules/typeColonSpacing/evaluateObjectTypeProperty.js
@@ -0,0 +1,42 @@
+import {getParameterName, quoteName} from '../../utilities';
+
+const getColon = (context, objectTypeProperty) => {
+  let tokenIndex = 1; // eslint-disable-line init-declarations
+
+  if (objectTypeProperty.optional) {
+    tokenIndex++;
+  }
+
+  if (objectTypeProperty.static) {
+    tokenIndex++;
+  }
+
+  if (objectTypeProperty.variance) {
+    tokenIndex++;
+  }
+
+  return context.getSourceCode().getFirstToken(objectTypeProperty, tokenIndex);
+};
+
+// 1) type X = { foo(): A; }
+// 2) type X = { foo: () => A; }
+// the above have identical ASTs (save for their ranges)
+// case 1 doesn't have a type annotation colon and should be ignored
+const isShortPropertyFunction = (objectTypeProperty) => {
+  return objectTypeProperty.value.type === 'FunctionTypeAnnotation' && objectTypeProperty.start === objectTypeProperty.value.start;
+};
+
+export default (context, report) => {
+  return (objectTypeProperty) => {
+    if (isShortPropertyFunction(objectTypeProperty)) {
+      // potential difference: not checked in before
+      return;
+    }
+
+    report({
+      colon: getColon(context, objectTypeProperty),
+      name: quoteName(getParameterName(objectTypeProperty, context)),
+      node: objectTypeProperty
+    });
+  };
+};
diff --git a/src/rules/typeColonSpacing/evaluateReturnType.js b/src/rules/typeColonSpacing/evaluateReturnType.js
new file mode 100644
index 0000000..d1815fb
--- /dev/null
+++ b/src/rules/typeColonSpacing/evaluateReturnType.js
@@ -0,0 +1,16 @@
+export default (context, report) => {
+  const sourceCode = context.getSourceCode();
+
+  return (functionNode) => {
+    // skip FunctionTypeAnnotation, possibly another rule as it's an arrow, not a colon?
+    // (foo: number) => string
+    //              ^^^^
+    if (functionNode.returnType && functionNode.type !== 'FunctionTypeAnnotation') {
+      report({
+        colon: sourceCode.getFirstToken(functionNode.returnType),
+        node: functionNode,
+        type: 'return type'
+      });
+    }
+  };
+};
diff --git a/src/rules/typeColonSpacing/evaluateTypeCastExpression.js b/src/rules/typeColonSpacing/evaluateTypeCastExpression.js
new file mode 100644
index 0000000..bf77f9f
--- /dev/null
+++ b/src/rules/typeColonSpacing/evaluateTypeCastExpression.js
@@ -0,0 +1,11 @@
+export default (context, report) => {
+  const sourceCode = context.getSourceCode();
+
+  return (typeCastExpression) => {
+    report({
+      colon: sourceCode.getFirstToken(typeCastExpression.typeAnnotation),
+      node: typeCastExpression,
+      type: 'type cast'
+    });
+  };
+};
diff --git a/src/rules/typeColonSpacing/evaluateTypical.js b/src/rules/typeColonSpacing/evaluateTypical.js
new file mode 100644
index 0000000..c2228d2
--- /dev/null
+++ b/src/rules/typeColonSpacing/evaluateTypical.js
@@ -0,0 +1,27 @@
+import _ from 'lodash';
+import {getParameterName, quoteName} from '../../utilities';
+
+export default (context, report, typeForMessage) => {
+  const sourceCode = context.getSourceCode();
+
+  const getColon = (node, typeAnnotation) => {
+    if (node.type === 'FunctionTypeParam') {
+      return sourceCode.getFirstToken(node, node.optional ? 2 : 1);
+    } else {
+      return sourceCode.getFirstToken(typeAnnotation);
+    }
+  };
+
+  return (node) => {
+    const typeAnnotation = _.get(node, 'typeAnnotation') || _.get(node, 'left.typeAnnotation');
+
+    if (typeAnnotation) {
+      report({
+        colon: getColon(node, typeAnnotation),
+        name: quoteName(getParameterName(node, context)),
+        node,
+        type: typeForMessage + ' type annotation'
+      });
+    }
+  };
+};
diff --git a/src/rules/typeColonSpacing/index.js b/src/rules/typeColonSpacing/index.js
new file mode 100644
index 0000000..2bfa3c2
--- /dev/null
+++ b/src/rules/typeColonSpacing/index.js
@@ -0,0 +1,18 @@
+import reporter from './reporter';
+import evaluateObjectTypeIndexer from './evaluateObjectTypeIndexer';
+import evaluateObjectTypeProperty from './evaluateObjectTypeProperty';
+import evaluateTypeCastExpression from './evaluateTypeCastExpression';
+import evaluateTypical from './evaluateTypical';
+import evaluateFunctions from './evaluateFunctions';
+
+export default (direction, context, options) => {
+  const report = reporter(direction, context, options);
+
+  return {
+    ...evaluateFunctions(context, report),
+    ClassProperty: evaluateTypical(context, report, 'class property'),
+    ObjectTypeIndexer: evaluateObjectTypeIndexer(context, report),
+    ObjectTypeProperty: evaluateObjectTypeProperty(context, report),
+    TypeCastExpression: evaluateTypeCastExpression(context, report)
+  };
+};
diff --git a/src/rules/typeColonSpacing/reporter.js b/src/rules/typeColonSpacing/reporter.js
new file mode 100644
index 0000000..5e17512
--- /dev/null
+++ b/src/rules/typeColonSpacing/reporter.js
@@ -0,0 +1,45 @@
+import {spacingFixers} from '../../utilities';
+
+const getSpaces = (direction, colon, context) => {
+  const sourceCode = context.getSourceCode();
+
+  if (direction === 'before') {
+    return colon.start - sourceCode.getTokenBefore(colon).end;
+  } else {
+    return sourceCode.getTokenAfter(colon).start - colon.end;
+  }
+};
+
+export default (direction, context, {always}) => {
+  return ({colon, node, name = '', type = 'type annotation'}) => {
+    const spaces = getSpaces(direction, colon, context);
+    const data = {
+      direction,
+      name,
+      type
+    };
+
+    if (always && spaces > 1) {
+      context.report({
+        data,
+        fix: spacingFixers.stripSpaces(direction, colon, spaces - 1),
+        message: 'There must be 1 space {{direction}} {{name}}{{type}} colon.',
+        node
+      });
+    } else if (always && spaces === 0) {
+      context.report({
+        data,
+        fix: spacingFixers.addSpace(direction, colon),
+        message: 'There must be a space {{direction}} {{name}}{{type}} colon.',
+        node
+      });
+    } else if (!always && spaces > 0) {
+      context.report({
+        data,
+        fix: spacingFixers.stripSpaces(direction, colon, spaces),
+        message: 'There must be no space {{direction}} {{name}}{{type}} colon.',
+        node
+      });
+    }
+  };
+};
diff --git a/src/rules/typeIdMatch.js b/src/rules/typeIdMatch.js
new file mode 100644
index 0000000..a3d5a8d
--- /dev/null
+++ b/src/rules/typeIdMatch.js
@@ -0,0 +1,22 @@
+export const schema = [
+  {
+    type: 'string'
+  }
+];
+
+export default (context) => {
+  const pattern = new RegExp(context.options[0] || '^([A-Z][a-z0-9]*)+Type$');
+
+  return {
+    TypeAlias (typeAliasNode) {
+      const typeIdentifierName = typeAliasNode.id.name;
+
+      if (!pattern.test(typeIdentifierName)) {
+        context.report(typeAliasNode, 'Type identifier \'{{name}}\' does not match pattern \'{{pattern}}\'.', {
+          name: typeIdentifierName,
+          pattern: pattern.toString()
+        });
+      }
+    }
+  };
+};
diff --git a/src/rules/unionIntersectionSpacing.js b/src/rules/unionIntersectionSpacing.js
new file mode 100644
index 0000000..5295798
--- /dev/null
+++ b/src/rules/unionIntersectionSpacing.js
@@ -0,0 +1,67 @@
+import {spacingFixers, getTokenAfterParens} from '../utilities';
+
+export default (context) => {
+  const sourceCode = context.getSourceCode();
+
+  const always = (context.options[0] || 'always') === 'always';
+
+  const check = (node) => {
+    node.types.forEach((type, index) => {
+      if (index + 1 === node.types.length) {
+        return;
+      }
+
+      const separator = getTokenAfterParens(sourceCode, type);
+      const endOfType = sourceCode.getTokenBefore(separator);
+      const nextType = sourceCode.getTokenAfter(separator);
+
+      const spaceBefore = separator.start - endOfType.end;
+      const spaceAfter = nextType.start - separator.end;
+
+      const data = {type: node.type === 'UnionTypeAnnotation' ? 'union' : 'intersection'};
+
+      if (always) {
+        if (!spaceBefore) {
+          context.report({
+            data,
+            fix: spacingFixers.addSpaceAfter(endOfType),
+            message: 'There must be a space before {{type}} type annotation separator',
+            node
+          });
+        }
+
+        if (!spaceAfter) {
+          context.report({
+            data,
+            fix: spacingFixers.addSpaceAfter(separator),
+            message: 'There must be a space after {{type}} type annotation separator',
+            node
+          });
+        }
+      } else {
+        if (spaceBefore) {
+          context.report({
+            data,
+            fix: spacingFixers.stripSpacesAfter(endOfType, spaceBefore),
+            message: 'There must be no space before {{type}} type annotation separator',
+            node
+          });
+        }
+
+        if (spaceAfter) {
+          context.report({
+            data,
+            fix: spacingFixers.stripSpacesAfter(separator, spaceAfter),
+            message: 'There must be no space after {{type}} type annotation separator',
+            node
+          });
+        }
+      }
+    });
+  };
+
+  return {
+    IntersectionTypeAnnotation: check,
+    UnionTypeAnnotation: check
+  };
+};
diff --git a/src/rules/useFlowType.js b/src/rules/useFlowType.js
new file mode 100644
index 0000000..947fc7e
--- /dev/null
+++ b/src/rules/useFlowType.js
@@ -0,0 +1,36 @@
+export const schema = [];
+
+export default (context) => {
+  const markTypeAsUsed = (node) => {
+    context.markVariableAsUsed(node.id.name);
+  };
+
+  return {
+    DeclareClass: markTypeAsUsed,
+    DeclareFunction: markTypeAsUsed,
+    DeclareModule: markTypeAsUsed,
+    DeclareVariable: markTypeAsUsed,
+    GenericTypeAnnotation (node) {
+      let typeId;
+      let scope;
+      let variable;
+
+      if (node.id.type === 'Identifier') {
+        typeId = node.id;
+      } else if (node.id.type === 'QualifiedTypeIdentifier') {
+        typeId = node.id;
+        do {
+          typeId = typeId.qualification;
+        } while (typeId.qualification);
+      }
+
+      for (scope = context.getScope(); scope; scope = scope.upper) {
+        variable = scope.set.get(typeId.name);
+        if (variable && variable.defs.length) {
+          context.markVariableAsUsed(typeId.name);
+          break;
+        }
+      }
+    }
+  };
+};
diff --git a/src/rules/validSyntax.js b/src/rules/validSyntax.js
new file mode 100644
index 0000000..4bf2c1d
--- /dev/null
+++ b/src/rules/validSyntax.js
@@ -0,0 +1,27 @@
+import _ from 'lodash';
+import {
+    getParameterName,
+    iterateFunctionNodes,
+    quoteName
+} from './../utilities';
+
+export default iterateFunctionNodes((context) => {
+  return (functionNode) => {
+    _.forEach(functionNode.params, (identifierNode) => {
+      const nodeType = _.get(identifierNode, 'type');
+      const isAssignmentPattern = nodeType === 'AssignmentPattern';
+      const hasTypeAnnotation = Boolean(_.get(identifierNode, 'typeAnnotation'));
+      const leftAnnotated = Boolean(_.get(identifierNode, 'left.typeAnnotation'));
+
+      if (isAssignmentPattern && hasTypeAnnotation && !leftAnnotated) {
+        context.report({
+          data: {
+            name: quoteName(getParameterName(identifierNode, context))
+          },
+          message: '{{name}}parameter type annotation must be placed on left-hand side of assignment.',
+          node: identifierNode
+        });
+      }
+    });
+  };
+});
diff --git a/src/utilities/getParameterName.js b/src/utilities/getParameterName.js
new file mode 100644
index 0000000..f341c63
--- /dev/null
+++ b/src/utilities/getParameterName.js
@@ -0,0 +1,52 @@
+import _ from 'lodash';
+
+export default (identifierNode, context) => {
+  if (_.has(identifierNode, 'name')) {
+    return identifierNode.name;
+  }
+
+  if (_.has(identifierNode, 'left.name')) {
+    return identifierNode.left.name;
+  }
+
+  if (_.has(identifierNode, 'key.name')) {
+    return identifierNode.key.name;
+  }
+
+  if (identifierNode.type === 'RestElement') {
+    return identifierNode.argument.name;
+  }
+
+  if (identifierNode.type === 'ObjectTypeProperty') {
+    let tokenIndex = 0; // eslint-disable-line init-declarations
+
+    if (identifierNode.static) {
+      tokenIndex++;
+    }
+
+    if (identifierNode.variance) {
+      tokenIndex++;
+    }
+
+    return context.getSourceCode().getFirstToken(identifierNode, tokenIndex).value;
+  }
+
+  if (identifierNode.type === 'FunctionTypeParam') {
+    return context.getSourceCode().getFirstToken(identifierNode).value;
+  }
+
+  if (identifierNode.type === 'ObjectPattern' || identifierNode.type === 'ArrayPattern') {
+    const text = context.getSourceCode().getText(identifierNode);
+
+    if (identifierNode.typeAnnotation) {
+      return text.replace(context.getSourceCode().getText(identifierNode.typeAnnotation), '').trim();
+    } else {
+      return text;
+    }
+  }
+  if (_.get(identifierNode, 'left.type') === 'ObjectPattern') {
+    return context.getSourceCode().getText(identifierNode.left);
+  }
+
+  return null;
+};
diff --git a/src/utilities/getTokenAfterParens.js b/src/utilities/getTokenAfterParens.js
new file mode 100644
index 0000000..c4d6f25
--- /dev/null
+++ b/src/utilities/getTokenAfterParens.js
@@ -0,0 +1,13 @@
+const getTokenAfterParens = (sourceCode, node) => {
+  let token;
+
+  token = sourceCode.getTokenAfter(node);
+
+  while (token.type === 'Punctuator' && token.value === ')') {
+    token = sourceCode.getTokenAfter(token);
+  }
+
+  return token;
+};
+
+export default getTokenAfterParens;
diff --git a/src/utilities/getTokenBeforeParens.js b/src/utilities/getTokenBeforeParens.js
new file mode 100644
index 0000000..1bd0417
--- /dev/null
+++ b/src/utilities/getTokenBeforeParens.js
@@ -0,0 +1,13 @@
+const getTokenBeforeParens = (sourceCode, node) => {
+  let token;
+
+  token = sourceCode.getTokenBefore(node);
+
+  while (token.type === 'Punctuator' && token.value === '(') {
+    token = sourceCode.getTokenBefore(token);
+  }
+
+  return token;
+};
+
+export default getTokenBeforeParens;
diff --git a/src/utilities/index.js b/src/utilities/index.js
new file mode 100644
index 0000000..3ef344d
--- /dev/null
+++ b/src/utilities/index.js
@@ -0,0 +1,10 @@
+'create index';
+
+export getParameterName from './getParameterName.js';
+export isFlowFile from './isFlowFile.js';
+export isFlowFileAnnotation from './isFlowFileAnnotation.js';
+export iterateFunctionNodes from './iterateFunctionNodes.js';
+export * as spacingFixers from './spacingFixers';
+export quoteName from './quoteName';
+export getTokenBeforeParens from './getTokenBeforeParens';
+export getTokenAfterParens from './getTokenAfterParens';
diff --git a/src/utilities/isFlowFile.js b/src/utilities/isFlowFile.js
new file mode 100644
index 0000000..73660ff
--- /dev/null
+++ b/src/utilities/isFlowFile.js
@@ -0,0 +1,13 @@
+import isFlowFileAnnotation from './isFlowFileAnnotation.js';
+
+export default (context) => {
+  const comments = context.getAllComments();
+
+  if (!comments.length) {
+    return false;
+  }
+
+  const firstComment = comments[0];
+
+  return isFlowFileAnnotation(firstComment.value);
+};
diff --git a/src/utilities/isFlowFileAnnotation.js b/src/utilities/isFlowFileAnnotation.js
new file mode 100644
index 0000000..ee4ed8a
--- /dev/null
+++ b/src/utilities/isFlowFileAnnotation.js
@@ -0,0 +1,13 @@
+import _ from 'lodash';
+
+const FLOW_MATCHER = /^@(?:no)?flow$/;
+
+export default (comment) => {
+  // eslint-disable-next-line flowtype/require-valid-file-annotation
+  // The flow parser splits comments with the following regex to look for the @flow flag.
+  // See https://github.com/facebook/flow/blob/a96249b93541f2f7bfebd8d62085bf7a75de02f2/src/parsing/docblock.ml#L39
+  return _.some(comment.split(/[ \t\r\n\\*/]+/), (commentPart) => {
+    return FLOW_MATCHER.test(commentPart);
+  });
+};
+
diff --git a/src/utilities/iterateFunctionNodes.js b/src/utilities/iterateFunctionNodes.js
new file mode 100644
index 0000000..c8e0988
--- /dev/null
+++ b/src/utilities/iterateFunctionNodes.js
@@ -0,0 +1,12 @@
+export default (iterator) => {
+  return (context, ...rest) => {
+    const nodeIterator = iterator(context, ...rest);
+
+    return {
+      ArrowFunctionExpression: nodeIterator,
+      FunctionDeclaration: nodeIterator,
+      FunctionExpression: nodeIterator,
+      FunctionTypeAnnotation: nodeIterator
+    };
+  };
+};
diff --git a/src/utilities/quoteName.js b/src/utilities/quoteName.js
new file mode 100644
index 0000000..2106d8f
--- /dev/null
+++ b/src/utilities/quoteName.js
@@ -0,0 +1,3 @@
+export default (name) => {
+  return name ? '"' + name + '" ' : '';
+};
diff --git a/src/utilities/spacingFixers.js b/src/utilities/spacingFixers.js
new file mode 100644
index 0000000..d2e2f41
--- /dev/null
+++ b/src/utilities/spacingFixers.js
@@ -0,0 +1,39 @@
+export const stripSpacesBefore = (node, spaces) => {
+  return (fixer) => {
+    return fixer.removeRange([node.start - spaces, node.start]);
+  };
+};
+
+export const stripSpacesAfter = (node, spaces) => {
+  return (fixer) => {
+    return fixer.removeRange([node.end, node.end + spaces]);
+  };
+};
+
+export const addSpaceBefore = (node) => {
+  return (fixer) => {
+    return fixer.insertTextBefore(node, ' ');
+  };
+};
+
+export const addSpaceAfter = (node) => {
+  return (fixer) => {
+    return fixer.insertTextAfter(node, ' ');
+  };
+};
+
+export const stripSpaces = (direction, node, spaces) => {
+  if (direction === 'before') {
+    return stripSpacesBefore(node, spaces);
+  } else {
+    return stripSpacesAfter(node, spaces);
+  }
+};
+
+export const addSpace = (direction, node) => {
+  if (direction === 'before') {
+    return addSpaceBefore(node);
+  } else {
+    return addSpaceAfter(node);
+  }
+};
diff --git a/tests/rules/assertions/booleanStyle.js b/tests/rules/assertions/booleanStyle.js
new file mode 100644
index 0000000..dac6fe7
--- /dev/null
+++ b/tests/rules/assertions/booleanStyle.js
@@ -0,0 +1,34 @@
+export default {
+  invalid: [
+    {
+      code: 'type X = bool',
+      errors: [{message: 'Use "boolean", not "bool"'}],
+      output: 'type X = boolean'
+    },
+    {
+      code: 'type X = bool',
+      errors: [{message: 'Use "boolean", not "bool"'}],
+      options: ['boolean'],
+      output: 'type X = boolean'
+    },
+    {
+      code: 'type X = boolean',
+      errors: [{message: 'Use "bool", not "boolean"'}],
+      options: ['bool'],
+      output: 'type X = bool'
+    }
+  ],
+  valid: [
+    {
+      code: 'type X = boolean'
+    },
+    {
+      code: 'type X = boolean',
+      options: ['boolean']
+    },
+    {
+      code: 'type X = bool',
+      options: ['bool']
+    }
+  ]
+};
diff --git a/tests/rules/assertions/defineFlowType.js b/tests/rules/assertions/defineFlowType.js
new file mode 100644
index 0000000..95893d3
--- /dev/null
+++ b/tests/rules/assertions/defineFlowType.js
@@ -0,0 +1,219 @@
+import {
+    RuleTester
+} from 'eslint';
+import noUndefRule from 'eslint/lib/rules/no-undef';
+
+const VALID_WITH_DEFINE_FLOW_TYPE = [
+  {
+    code: 'var a: AType',
+    errors: [
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'var a: AType; var b: AType',
+    errors: [
+      '\'AType\' is not defined.',
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'var a; (a: AType)',
+    errors: [
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'var a: AType<BType>',
+    errors: [
+      '\'AType\' is not defined.',
+      '\'BType\' is not defined.'
+    ]
+  },
+  {
+    code: 'type A = AType',
+    errors: [
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'function f(a: AType) {}',
+    errors: [
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'function f(a: AType.a) {}',
+    errors: [
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'function f(a: AType.a.b) {}',
+    errors: [
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'function f(a): AType {}; var a: AType',
+    errors: [
+      '\'AType\' is not defined.',
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'function f(a): AType {}',
+    errors: [
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'class C { a: AType }',
+    errors: [
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'class C { a: AType.a }',
+    errors: [
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'class C { a: AType.a.b }',
+    errors: [
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'class C implements AType {}',
+    errors: [
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'interface AType {}',
+    errors: [
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: '({ a: ({b() {}}: AType) })',
+        // `AType` appears twice in `globalScope.through` as distinct
+        // references, this may be a babel-eslint bug.
+    errors: [
+      '\'AType\' is not defined.',
+      '\'AType\' is not defined.'
+    ]
+  },
+  {
+    code: 'type X = {Y<AType>(): BType}',
+    errors: [
+      '\'AType\' is not defined.',
+      '\'BType\' is not defined.'
+    ]
+  },
+  {
+    code: 'interface AType<BType> {}',
+    errors: [
+      '\'AType\' is not defined.',
+      '\'BType\' is not defined.'
+    ]
+  }
+];
+
+const ALWAYS_INVALID = [
+  {
+    code: 'var a = b',
+    errors: [
+      '\'b\' is not defined.'
+    ]
+  },
+  {
+    code: 'function f(a = b) {}',
+    errors: [
+      '\'b\' is not defined.'
+    ]
+  },
+  {
+    code: 'class C extends b {}',
+    errors: [
+      '\'b\' is not defined.'
+    ]
+  },
+  {
+    code: 'class C { static S = b }',
+    errors: [
+      '\'b\' is not defined.'
+    ]
+  }
+];
+
+const ALWAYS_VALID = [
+  'var a: string',
+  'var a: Array',
+  'var a: Array<string>',
+  'type A = Array',
+  'function f(a: string) {}',
+  'function f(a): string {}',
+  'class C { a: string }',
+  'var AType = {}; class C { a: AType.a }',
+  'declare module A { declare var a: AType }'
+];
+
+/**
+ * This rule is tested differently than the rest because `RuleTester` is
+ * designed to test rule reporting and define-flow-type doesn't report
+ * anything. define-flow-type suppresses reports from no-undef. So we're
+ * actually testing no-undef's reporting with define-flow-type enabled.
+ */
+{
+  const ruleTester = new RuleTester({
+    parser: 'babel-eslint'
+  });
+
+  ruleTester.run('no-under must not trigger an error in these cases', noUndefRule, {
+    invalid: [],
+    valid: ALWAYS_VALID
+  });
+}
+
+{
+  const ruleTester = new RuleTester({
+    parser: 'babel-eslint'
+  });
+
+  ruleTester.run('no-undef must trigger an error when define-flow-type is not used in these cases', noUndefRule, {
+    invalid: [
+      ...ALWAYS_INVALID,
+      ...VALID_WITH_DEFINE_FLOW_TYPE
+    ],
+    valid: []
+  });
+}
+
+export default {
+  invalid: [],
+  valid: [
+    ...VALID_WITH_DEFINE_FLOW_TYPE.map((subject) => {
+      return {
+        code: subject.code,
+        rules: {
+          'no-undef': 2
+        }
+      };
+    }),
+    ...VALID_WITH_DEFINE_FLOW_TYPE.map((subject) => {
+      return {
+        code: subject.code,
+        rules: {
+          'no-undef': 2,
+          'no-use-before-define': [
+            2,
+            'nofunc'
+          ]
+        }
+      };
+    })
+  ]
+};
diff --git a/tests/rules/assertions/delimiterDangle.js b/tests/rules/assertions/delimiterDangle.js
new file mode 100644
index 0000000..f4f2344
--- /dev/null
+++ b/tests/rules/assertions/delimiterDangle.js
@@ -0,0 +1,512 @@
+const OBJECT_TYPE_ANNOTATION = {
+  invalid: [
+    {
+      code: 'type X = { foo: string, }',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      output: 'type X = { foo: string }'
+    },
+    {
+      code: 'type X = { foo: string, }',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['never'],
+      output: 'type X = { foo: string }'
+    },
+    {
+      code: 'type X = { foo: string; }',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['never'],
+      output: 'type X = { foo: string }'
+    },
+    {
+      code: 'type X = {\nfoo: string,\n}',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['never'],
+      output: 'type X = {\nfoo: string\n}'
+    },
+    {
+      code: 'type X = { foo: string }',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always'],
+      output: 'type X = { foo: string, }'
+    },
+    {
+      code: 'type X = {\nfoo: string\n}',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always'],
+      output: 'type X = {\nfoo: string,\n}'
+    },
+    {
+      code: 'type X = { foo: string, }',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['always-multiline'],
+      output: 'type X = { foo: string }'
+    },
+    {
+      code: 'type X = {\nfoo: string\n}',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always-multiline'],
+      output: 'type X = {\nfoo: string,\n}'
+    },
+    {
+      code: 'type X = { foo: string; }',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['only-multiline'],
+      output: 'type X = { foo: string }'
+    },
+
+    // Only indexers...
+    {
+      code: 'type X = { [key: string]: number, }',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['never'],
+      output: 'type X = { [key: string]: number }'
+    },
+    {
+      code: 'type X = { [key: string]: number }',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always'],
+      output: 'type X = { [key: string]: number, }'
+    },
+    {
+      code: 'type X = { [key: string]: number, }',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['always-multiline'],
+      output: 'type X = { [key: string]: number }'
+    },
+    {
+      code: 'type X = {\n[key: string]: number\n}',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always-multiline'],
+      output: 'type X = {\n[key: string]: number,\n}'
+    },
+    {
+      code: 'type X = { [key: string]: number; }',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['only-multiline'],
+      output: 'type X = { [key: string]: number }'
+    },
+
+    // Indexer, Prop...
+    {
+      code: 'type X = { [key: string]: number, foo: string, }',
+      errors: [{
+        // be sure it's reporting the prop, not the indexer
+        column: 35,
+        line: 1,
+        message: 'Unexpected trailing delimiter'
+      }],
+      options: ['never'],
+      output: 'type X = { [key: string]: number, foo: string }'
+    },
+    {
+      code: 'type X = {\n[key: string]: number,\nfoo: string,\n}',
+      errors: [{
+        // be sure it's reporting the prop, not the indexer
+        column: 1,
+        line: 3,
+        message: 'Unexpected trailing delimiter'
+      }],
+      options: ['never'],
+      output: 'type X = {\n[key: string]: number,\nfoo: string\n}'
+    },
+    {
+      code: 'type X = {\n[key: string]: number,\naReallyLongPropertyNameHere: string,\n}',
+      errors: [{
+        // be sure it's reporting the prop, not the indexer
+        column: 1,
+        line: 3,
+        message: 'Unexpected trailing delimiter'
+      }],
+      options: ['never'],
+      output: 'type X = {\n[key: string]: number,\naReallyLongPropertyNameHere: string\n}'
+    },
+    {
+      code: 'type X = { [key: string]: number, foo: string }',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always'],
+      output: 'type X = { [key: string]: number, foo: string, }'
+    },
+    {
+      code: 'type X = {\n[key: string]: number;\nfoo: string\n}',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always'],
+      output: 'type X = {\n[key: string]: number;\nfoo: string,\n}'
+    },
+    {
+      code: 'type X = { [key: string]: number, foo: string, }',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['always-multiline'],
+      output: 'type X = { [key: string]: number, foo: string }'
+    },
+    {
+      code: 'type X = {\n[key: string]: number,\nfoo: string\n}',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always-multiline'],
+      output: 'type X = {\n[key: string]: number,\nfoo: string,\n}'
+    },
+    {
+      code: 'type X = { [key: string]: number, foo: string, }',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['only-multiline'],
+      output: 'type X = { [key: string]: number, foo: string }'
+    },
+
+    // Prop, Indexer...
+    {
+      code: 'type X = { foo: string, [key: string]: number, }',
+      errors: [{
+        // be sure it's reporting the indexer, not the prop
+        column: 25,
+        line: 1,
+        message: 'Unexpected trailing delimiter'
+      }],
+      options: ['never'],
+      output: 'type X = { foo: string, [key: string]: number }'
+    },
+    {
+      code: 'type X = {\nfoo: string,\n[key: string]: number,\n}',
+      errors: [{
+        // be sure it's reporting the prop, not the indexer
+        column: 1,
+        line: 3,
+        message: 'Unexpected trailing delimiter'
+      }],
+      options: ['never'],
+      output: 'type X = {\nfoo: string,\n[key: string]: number\n}'
+    },
+    {
+      code: 'type X = {\naReallyLongPropertyNameHere: string,\n[key: string]: number,\n}',
+      errors: [{
+        // be sure it's reporting the prop, not the indexer
+        column: 1,
+        line: 3,
+        message: 'Unexpected trailing delimiter'
+      }],
+      options: ['never'],
+      output: 'type X = {\naReallyLongPropertyNameHere: string,\n[key: string]: number\n}'
+    },
+    {
+      code: 'type X = { foo: string, [key: string]: number }',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always'],
+      output: 'type X = { foo: string, [key: string]: number, }'
+    },
+    {
+      code: 'type X = { foo: string; [key: string]: number }',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always'],
+      output: 'type X = { foo: string; [key: string]: number, }'
+    },
+    {
+      code: 'type X = { foo: string, [key: string]: number; }',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['always-multiline'],
+      output: 'type X = { foo: string, [key: string]: number }'
+    },
+    {
+      code: 'type X = {\nfoo: string,\n[key: string]: number\n}',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always-multiline'],
+      output: 'type X = {\nfoo: string,\n[key: string]: number,\n}'
+    },
+    {
+      code: 'type X = { foo: string, [key: string]: number; }',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['only-multiline'],
+      output: 'type X = { foo: string, [key: string]: number }'
+    }
+  ],
+  valid: [
+    {
+      code: 'type X = { foo: string }'
+    },
+    {
+      code: 'type X = { foo: string }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { foo: string, }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { foo: string; }',
+      options: ['always']
+    },
+    {
+      code: 'type X = {\nfoo: string\n}',
+      options: ['never']
+    },
+    {
+      code: 'type X = {\nfoo: string,\n}',
+      options: ['always']
+    },
+    {
+      code: 'type X = { foo: string }',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = {\nfoo: string,\n}',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = {\nfoo: string;\n}',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = { foo: string }',
+      options: ['only-multiline']
+    },
+    {
+      code: 'type X = {\nfoo: string\n}',
+      options: ['only-multiline']
+    },
+    {
+      code: 'type X = {\nfoo: string,\n}',
+      options: ['only-multiline']
+    },
+    {
+      code: 'type X = {\nfoo: string;\n}',
+      options: ['only-multiline']
+    },
+
+    // Empty...
+    {
+      code: 'type X = {}',
+      options: ['never']
+    },
+    {
+      code: 'type X = {}',
+      options: ['always']
+    },
+    {
+      code: 'type X = {}',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = {}',
+      options: ['only-multiline']
+    },
+
+    // Only indexers...
+    {
+      code: 'type X = { [key: string]: number }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { [key: string]: number, }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { [key: string]: number; }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { [key: string]: number }',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = {\n[key: string]: number,\n}',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = {\n[key: string]: number,\n}',
+      options: ['only-multiline']
+    },
+    {
+      code: 'type X = {\n[key: string]: number\n}',
+      options: ['only-multiline']
+    },
+    {
+      code: 'type X = { [key: string]: number }',
+      options: ['only-multiline']
+    },
+
+    // Indexer, Prop...
+    {
+      code: 'type X = { [key: string]: number, foo: string }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { [key: string]: number, foo: string, }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { [key: string]: number; foo: string; }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { [key: string]: number, foo: string }',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = {\n[key: string]: number,\nfoo: string,\n}',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = {\n[key: string]: number,\nfoo: string,\n}',
+      options: ['only-multiline']
+    },
+    {
+      code: 'type X = {\n[key: string]: number;\nfoo: string\n}',
+      options: ['only-multiline']
+    },
+    {
+      code: 'type X = { [key: string]: number, foo: string }',
+      options: ['only-multiline']
+    },
+
+    // Prop, Indexer...
+    {
+      code: 'type X = { foo: string, [key: string]: number }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { foo: string, [key: string]: number, }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { foo: string; [key: string]: number; }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { foo: string, [key: string]: number }',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = {\nfoo: string,\n[key: string]: number,\n}',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = {\nfoo: string,\n[key: string]: number,\n}',
+      options: ['only-multiline']
+    },
+    {
+      code: 'type X = {\nfoo: string;\n[key: string]: number\n}',
+      options: ['only-multiline']
+    },
+    {
+      code: 'type X = { foo: string, [key: string]: number }',
+      options: ['only-multiline']
+    }
+  ]
+};
+
+const TUPLE_TYPE_ANNOTATION = {
+  invalid: [
+    {
+      code: 'type X = [string, number,]',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      output: 'type X = [string, number]'
+    },
+    {
+      code: 'type X = [string, number,]',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['never'],
+      output: 'type X = [string, number]'
+    },
+    {
+      code: 'type X = [\nstring,\nnumber,\n]',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['never'],
+      output: 'type X = [\nstring,\nnumber\n]'
+    },
+    {
+      code: 'type X = [string, number]',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always'],
+      output: 'type X = [string, number,]'
+    },
+    {
+      code: 'type X = [\nstring,\nnumber\n]',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always'],
+      output: 'type X = [\nstring,\nnumber,\n]'
+    },
+    {
+      code: 'type X = [string, number,]',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['always-multiline'],
+      output: 'type X = [string, number]'
+    },
+    {
+      code: 'type X = [\nfoo, string\n]',
+      errors: [{message: 'Missing trailing delimiter'}],
+      options: ['always-multiline'],
+      output: 'type X = [\nfoo, string,\n]'
+    },
+    {
+      code: 'type X = [ number, string, ]',
+      errors: [{message: 'Unexpected trailing delimiter'}],
+      options: ['only-multiline'],
+      output: 'type X = [ number, string ]'
+    }
+  ],
+  valid: [
+    {
+      code: 'type X = [string, number]'
+    },
+    {
+      code: 'type X = [string, number]',
+      options: ['never']
+    },
+    {
+      code: 'type X = [\nstring,\nnumber\n]',
+      options: ['never']
+    },
+    {
+      code: 'type X = [string, number,]',
+      options: ['always']
+    },
+    {
+      code: 'type X = [\nstring,\nnumber,\n]',
+      options: ['always']
+    },
+    {
+      code: 'type X = [ foo, string ]',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = [\nfoo, string,\n]',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = [ number, string ]',
+      options: ['only-multiline']
+    },
+    {
+      code: 'type X = [\nnumber,\nstring\n]',
+      options: ['only-multiline']
+    },
+    {
+      code: 'type X = [\nnumber,\nstring,\n]',
+      options: ['only-multiline']
+    },
+    {
+      code: 'type X = []',
+      options: ['never']
+    },
+    {
+      code: 'type X = []',
+      options: ['always']
+    },
+    {
+      code: 'type X = []',
+      options: ['always-multiline']
+    },
+    {
+      code: 'type X = []',
+      options: ['only-multiline']
+    }
+  ]
+};
+
+export default {
+  invalid: [
+    ...OBJECT_TYPE_ANNOTATION.invalid,
+    ...TUPLE_TYPE_ANNOTATION.invalid
+  ],
+  valid: [
+    ...OBJECT_TYPE_ANNOTATION.valid,
+    ...TUPLE_TYPE_ANNOTATION.valid
+  ]
+};
diff --git a/tests/rules/assertions/genericSpacing.js b/tests/rules/assertions/genericSpacing.js
new file mode 100644
index 0000000..727f5bb
--- /dev/null
+++ b/tests/rules/assertions/genericSpacing.js
@@ -0,0 +1,117 @@
+export default {
+  invalid: [
+        // Never
+
+    {
+      code: 'type X = Promise< string>',
+      errors: [{message: 'There must be no space at start of "Promise" generic type annotation'}],
+      output: 'type X = Promise<string>'
+    },
+    {
+      code: 'type X = Promise<  string>',
+      errors: [{message: 'There must be no space at start of "Promise" generic type annotation'}],
+      options: ['never'],
+      output: 'type X = Promise<string>'
+    },
+    {
+      code: 'type X = FooBar<string >',
+      errors: [{message: 'There must be no space at end of "FooBar" generic type annotation'}],
+      output: 'type X = FooBar<string>'
+    },
+    {
+      code: 'type X = Promise< string >',
+      errors: [
+                {message: 'There must be no space at start of "Promise" generic type annotation'},
+                {message: 'There must be no space at end of "Promise" generic type annotation'}
+      ],
+      output: 'type X = Promise<string>'
+    },
+    {
+      code: 'type X = Promise< (foo), bar, (((baz))) >',
+      errors: [
+                {message: 'There must be no space at start of "Promise" generic type annotation'},
+                {message: 'There must be no space at end of "Promise" generic type annotation'}
+      ],
+      output: 'type X = Promise<(foo), bar, (((baz)))>'
+    },
+
+        // Always (given no space)
+
+    {
+      code: 'type X = Promise<string >',
+      errors: [{message: 'There must be a space at start of "Promise" generic type annotation'}],
+      options: ['always'],
+      output: 'type X = Promise< string >'
+    },
+    {
+      code: 'type X = FooBar< string>',
+      errors: [{message: 'There must be a space at end of "FooBar" generic type annotation'}],
+      options: ['always'],
+      output: 'type X = FooBar< string >'
+    },
+    {
+      code: 'type X = Promise<string>',
+      errors: [
+                {message: 'There must be a space at start of "Promise" generic type annotation'},
+                {message: 'There must be a space at end of "Promise" generic type annotation'}
+      ],
+      options: ['always'],
+      output: 'type X = Promise< string >'
+    },
+    {
+      code: 'type X = Promise<(foo), bar, (((baz)))>',
+      errors: [
+                {message: 'There must be a space at start of "Promise" generic type annotation'},
+                {message: 'There must be a space at end of "Promise" generic type annotation'}
+      ],
+      options: ['always'],
+      output: 'type X = Promise< (foo), bar, (((baz))) >'
+    },
+
+        // Always (given too many spaces)
+
+    {
+      code: 'type X = FooBar<  string >',
+      errors: [{message: 'There must be one space at start of "FooBar" generic type annotation'}],
+      options: ['always'],
+      output: 'type X = FooBar< string >'
+    },
+    {
+      code: 'type X = FooBar< string  >',
+      errors: [{message: 'There must be one space at end of "FooBar" generic type annotation'}],
+      options: ['always'],
+      output: 'type X = FooBar< string >'
+    },
+    {
+      code: 'type X = Promise<  (foo), bar, (((baz)))  >',
+      errors: [
+                {message: 'There must be one space at start of "Promise" generic type annotation'},
+                {message: 'There must be one space at end of "Promise" generic type annotation'}
+      ],
+      options: ['always'],
+      output: 'type X = Promise< (foo), bar, (((baz))) >'
+    }
+  ],
+  valid: [
+        // Never
+
+        {code: 'type X = Promise<string>'},
+        {code: 'type X = Promise<(string)>'},
+        {code: 'type X = Promise<(foo), bar, (((baz)))>'},
+
+        // Always
+
+    {
+      code: 'type X = Promise< string >',
+      options: ['always']
+    },
+    {
+      code: 'type X = Promise< (string) >',
+      options: ['always']
+    },
+    {
+      code: 'type X = Promise< (foo), bar, (((baz))) >',
+      options: ['always']
+    }
+  ]
+};
diff --git a/tests/rules/assertions/noDupeKeys.js b/tests/rules/assertions/noDupeKeys.js
new file mode 100644
index 0000000..717ade5
--- /dev/null
+++ b/tests/rules/assertions/noDupeKeys.js
@@ -0,0 +1,17 @@
+export default {
+  invalid: [
+    {
+      code: 'type FooType = { a: number, b: string, a: number }',
+      errors: [{message: 'Duplicate property.'}]
+    },
+    {
+      code: 'type FooType = { a: number, b: string, a: string }',
+      errors: [{message: 'Duplicate property.'}]
+    }
+  ],
+  valid: [
+    {
+      code: 'type FooType = { a: number, b: string, c: number }'
+    }
+  ]
+};
diff --git a/tests/rules/assertions/noWeakTypes.js b/tests/rules/assertions/noWeakTypes.js
new file mode 100644
index 0000000..ce8c933
--- /dev/null
+++ b/tests/rules/assertions/noWeakTypes.js
@@ -0,0 +1,251 @@
+export default {
+  invalid: [
+    {
+      code: 'function foo(thing): any {}',
+      errors: [{
+        message: 'Unexpected use of weak type "any"'
+      }]
+    },
+    {
+      code: 'function foo(thing): Promise<any> {}',
+      errors: [{
+        message: 'Unexpected use of weak type "any"'
+      }]
+    },
+    {
+      code: 'function foo(thing): Promise<Promise<any>> {}',
+      errors: [{
+        message: 'Unexpected use of weak type "any"'
+      }]
+    },
+    {
+      code: 'function foo(thing): Object {}',
+      errors: [{
+        message: 'Unexpected use of weak type "Object"'
+      }]
+    },
+    {
+      code: 'function foo(thing): Promise<Object> {}',
+      errors: [{
+        message: 'Unexpected use of weak type "Object"'
+      }]
+    },
+    {
+      code: 'function foo(thing): Promise<Promise<Object>> {}',
+      errors: [{
+        message: 'Unexpected use of weak type "Object"'
+      }]
+    },
+    {
+      code: 'function foo(thing): Function {}',
+      errors: [{
+        message: 'Unexpected use of weak type "Function"'
+      }]
+    },
+    {
+      code: 'function foo(thing): Promise<Function> {}',
+      errors: [{
+        message: 'Unexpected use of weak type "Function"'
+      }]
+    },
+    {
+      code: 'function foo(thing): Promise<Promise<Function>> {}',
+      errors: [{
+        message: 'Unexpected use of weak type "Function"'
+      }]
+    },
+    {
+      code: '(foo: any) => {}',
+      errors: [{
+        message: 'Unexpected use of weak type "any"'
+      }]
+    },
+    {
+      code: '(foo: Function) => {}',
+      errors: [{
+        message: 'Unexpected use of weak type "Function"'
+      }]
+    },
+    {
+      code: '(foo?: any) => {}',
+      errors: [{
+        message: 'Unexpected use of weak type "any"'
+      }]
+    },
+    {
+      code: '(foo?: Function) => {}',
+      errors: [{
+        message: 'Unexpected use of weak type "Function"'
+      }]
+    },
+    {
+      code: '(foo: { a: any }) => {}',
+      errors: [{
+        message: 'Unexpected use of weak type "any"'
+      }]
+    },
+    {
+      code: '(foo: { a: Object }) => {}',
+      errors: [{
+        message: 'Unexpected use of weak type "Object"'
+      }]
+    },
+    {
+      code: '(foo: any[]) => {}',
+      errors: [{
+        message: 'Unexpected use of weak type "any"'
+      }]
+    },
+    {
+      code: 'type Foo = any',
+      errors: [{
+        message: 'Unexpected use of weak type "any"'
+      }]
+    },
+    {
+      code: 'type Foo = Function',
+      errors: [{
+        message: 'Unexpected use of weak type "Function"'
+      }]
+    },
+    {
+      code: 'type Foo = { a: any }',
+      errors: [{
+        message: 'Unexpected use of weak type "any"'
+      }]
+    },
+    {
+      code: 'type Foo = { a: Object }',
+      errors: [{
+        message: 'Unexpected use of weak type "Object"'
+      }]
+    },
+    {
+      code: 'type Foo = { (a: Object): string }',
+      errors: [{
+        message: 'Unexpected use of weak type "Object"'
+      }]
+    },
+    {
+      code: 'type Foo = { (a: string): Function }',
+      errors: [{
+        message: 'Unexpected use of weak type "Function"'
+      }]
+    },
+    {
+      code: 'function foo(thing: any) {}',
+      errors: [{
+        message: 'Unexpected use of weak type "any"'
+      }]
+    },
+    {
+      code: 'function foo(thing: Object) {}',
+      errors: [{
+        message: 'Unexpected use of weak type "Object"'
+      }]
+    },
+    {
+      code: 'var foo: Function',
+      errors: [{
+        message: 'Unexpected use of weak type "Function"'
+      }]
+    },
+    {
+      code: 'var foo: Object',
+      errors: [{
+        message: 'Unexpected use of weak type "Object"'
+      }]
+    },
+    {
+      code: 'class Foo { props: any }',
+      errors: [{
+        message: 'Unexpected use of weak type "any"'
+      }]
+    },
+    {
+      code: 'class Foo { props: Object }',
+      errors: [{
+        message: 'Unexpected use of weak type "Object"'
+      }]
+    },
+    {
+      code: 'var foo: any',
+      errors: [{
+        message: 'Unexpected use of weak type "any"'
+      }]
+    },
+    {
+      code: 'type X = any; type Y = Function; type Z = Object',
+      errors: [
+        {message: 'Unexpected use of weak type "any"'},
+        {message: 'Unexpected use of weak type "Object"'}
+      ],
+      options: [{
+        Function: false
+      }]
+    },
+    {
+      code: 'type X = any; type Y = Function; type Z = Object',
+      errors: [{message: 'Unexpected use of weak type "Function"'}],
+      options: [{
+        Object: false,
+        any: false
+      }]
+    }
+  ],
+  valid: [
+    {
+      code: 'function foo(thing): string {}'
+    },
+    {
+      code: 'function foo(thing): Promise<string> {}'
+    },
+    {
+      code: 'function foo(thing): Promise<Promise<string>> {}'
+    },
+    {
+      code: '(foo?: string) => {}'
+    },
+    {
+      code: '(foo: ?string) => {}'
+    },
+    {
+      code: '(foo: { a: string }) => {}'
+    },
+    {
+      code: '(foo: { a: ?string }) => {}'
+    },
+    {
+      code: '(foo: string[]) => {}'
+    },
+    {
+      code: 'type Foo = string'
+    },
+    {
+      code: 'type Foo = { a: string }'
+    },
+    {
+      code: 'type Foo = { (a: string): string }'
+    },
+    {
+      code: 'function foo(thing: string) {}'
+    },
+    {
+      code: 'var foo: string'
+    },
+    {
+      code: 'class Foo { props: string }'
+    },
+    {
+      code: 'type X = any; type Y = Object',
+      options: [{
+        Object: false,
+        any: false
+      }]
+    },
+    {
+      code: 'type X = Function',
+      options: [{Function: false}]
+    }
+  ]
+};
diff --git a/tests/rules/assertions/objectTypeDelimiter.js b/tests/rules/assertions/objectTypeDelimiter.js
new file mode 100644
index 0000000..90d0498
--- /dev/null
+++ b/tests/rules/assertions/objectTypeDelimiter.js
@@ -0,0 +1,147 @@
+export default {
+  invalid: [
+    {
+      code: 'type Foo = { a: Foo, b: Bar }',
+      errors: [{message: 'Prefer semicolons to commas in object and class types'}],
+      options: ['semicolon'],
+      output: 'type Foo = { a: Foo; b: Bar }'
+    },
+    {
+      code: 'type Foo = { a: Foo; b: Bar }',
+      errors: [{message: 'Prefer commas to semicolons in object and class types'}],
+      options: ['comma'],
+      output: 'type Foo = { a: Foo, b: Bar }'
+    },
+    {
+      code: 'type Foo = { [a: string]: Foo, [b: string]: Bar }',
+      errors: [{message: 'Prefer semicolons to commas in object and class types'}],
+      options: ['semicolon'],
+      output: 'type Foo = { [a: string]: Foo; [b: string]: Bar }'
+    },
+    {
+      code: 'type Foo = { [a: string]: Foo; [b: string]: Bar }',
+      errors: [{message: 'Prefer commas to semicolons in object and class types'}],
+      options: ['comma'],
+      output: 'type Foo = { [a: string]: Foo, [b: string]: Bar }'
+    },
+    {
+      code: 'type Foo = { (): Foo, (): Bar }',
+      errors: [{message: 'Prefer semicolons to commas in object and class types'}],
+      options: ['semicolon'],
+      output: 'type Foo = { (): Foo; (): Bar }'
+    },
+    {
+      code: 'type Foo = { (): Foo; (): Bar }',
+      errors: [{message: 'Prefer commas to semicolons in object and class types'}],
+      options: ['comma'],
+      output: 'type Foo = { (): Foo, (): Bar }'
+    },
+    {
+      code: 'declare class Foo { a: Foo, }',
+      errors: [{message: 'Prefer semicolons to commas in object and class types'}],
+      options: ['semicolon'],
+      output: 'declare class Foo { a: Foo; }'
+    },
+    {
+      code: 'declare class Foo { a: Foo; }',
+      errors: [{message: 'Prefer commas to semicolons in object and class types'}],
+      options: ['comma'],
+      output: 'declare class Foo { a: Foo, }'
+    },
+    {
+      code: 'declare class Foo { [a: string]: Foo, }',
+      errors: [{message: 'Prefer semicolons to commas in object and class types'}],
+      options: ['semicolon'],
+      output: 'declare class Foo { [a: string]: Foo; }'
+    },
+    {
+      code: 'declare class Foo { a: Foo; }',
+      errors: [{message: 'Prefer commas to semicolons in object and class types'}],
+      options: ['comma'],
+      output: 'declare class Foo { a: Foo, }'
+    },
+    {
+      code: 'declare class Foo { (): Foo, }',
+      errors: [{message: 'Prefer semicolons to commas in object and class types'}],
+      options: ['semicolon'],
+      output: 'declare class Foo { (): Foo; }'
+    },
+    {
+      code: 'declare class Foo { (): Foo; }',
+      errors: [{message: 'Prefer commas to semicolons in object and class types'}],
+      options: ['comma'],
+      output: 'declare class Foo { (): Foo, }'
+    },
+    {
+      code: 'declare class Foo { static (): Foo, }',
+      errors: [{message: 'Prefer semicolons to commas in object and class types'}],
+      options: ['semicolon'],
+      output: 'declare class Foo { static (): Foo; }'
+    },
+    {
+      code: 'declare class Foo { static (): Foo; }',
+      errors: [{message: 'Prefer commas to semicolons in object and class types'}],
+      options: ['comma'],
+      output: 'declare class Foo { static (): Foo, }'
+    }
+  ],
+  valid: [
+    {
+      code: 'type Foo = { a: Foo; b: Bar }',
+      options: ['semicolon']
+    },
+    {
+      code: 'type Foo = { a: Foo, b: Bar }',
+      options: ['comma']
+    },
+    {
+      code: 'type Foo = { [a: string]: Foo; [b: string]: Bar }',
+      options: ['semicolon']
+    },
+    {
+      code: 'type Foo = { [a: string]: Foo, [b: string]: Bar }',
+      options: ['comma']
+    },
+    {
+      code: 'type Foo = { (): Foo; (): Bar }',
+      options: ['semicolon']
+    },
+    {
+      code: 'type Foo = { (): Foo, (): Bar }',
+      options: ['comma']
+    },
+    {
+      code: 'type Foo = { a: Foo, b: Bar }'
+    },
+    {
+      code: 'type Foo = { [a: string]: Foo, [b: string]: Bar }'
+    },
+    {
+      code: 'type Foo = { (): Foo, (): Bar }'
+    },
+    {
+      code: 'declare class Foo { a: Foo; }',
+      options: ['semicolon']
+    },
+    {
+      code: 'declare class Foo { a: Foo, }',
+      options: ['comma']
+    },
+    {
+      code: 'declare class Foo { [a: string]: Foo; }',
+      options: ['semicolon']
+    },
+    {
+      code: 'declare class Foo { [a: string]: Foo, }',
+      options: ['comma']
+    },
+    {
+      code: 'declare class Foo { (): Foo; }',
+      options: ['semicolon']
+    },
+    {
+      code: 'declare class Foo { (): Foo, }',
+      options: ['comma']
+    }
+  ]
+};
diff --git a/tests/rules/assertions/requireParameterType.js b/tests/rules/assertions/requireParameterType.js
new file mode 100644
index 0000000..cbc25f2
--- /dev/null
+++ b/tests/rules/assertions/requireParameterType.js
@@ -0,0 +1,195 @@
+export default {
+  invalid: [
+    {
+      code: '(foo) => {}',
+      errors: [
+        {
+          message: 'Missing "foo" parameter type annotation.'
+        }
+      ]
+    },
+    {
+      code: 'function x(foo) {}',
+      errors: [
+        {
+          message: 'Missing "foo" parameter type annotation.'
+        }
+      ]
+    },
+    {
+      code: 'function x(foo) {}',
+      errors: [
+        {
+          message: 'Missing "foo" parameter type annotation.'
+        }
+      ],
+      options: [
+        {
+          excludeArrowFunctions: true
+        }
+      ]
+    },
+    {
+      code: '(foo = \'FOO\') => {}',
+      errors: [
+        {
+          message: 'Missing "foo" parameter type annotation.'
+        }
+      ]
+    },
+    {
+      code: '(...foo) => {}',
+      errors: [
+        {
+          message: 'Missing "foo" parameter type annotation.'
+        }
+      ]
+    },
+    {
+      code: '({foo}) => {}',
+      errors: [
+        {
+          message: 'Missing "{foo}" parameter type annotation.'
+        }
+      ]
+    },
+    {
+      code: '([foo]) => {}',
+      errors: [
+        {
+          message: 'Missing "[foo]" parameter type annotation.'
+        }
+      ]
+    },
+    {
+      code: '({foo = 1} = {}) => {}',
+      errors: [
+        {
+          message: 'Missing "{foo = 1}" parameter type annotation.'
+        }
+      ]
+    },
+    {
+      code: '// @flow\n(foo) => {}',
+      errors: [
+        {
+          message: 'Missing "foo" parameter type annotation.'
+        }
+      ],
+      settings: {
+        flowtype: {
+          onlyFilesWithFlowAnnotation: true
+        }
+      }
+    },
+    {
+      code: '(foo) => {}',
+      errors: [
+        {
+          message: 'Missing "foo" parameter type annotation.'
+        }
+      ],
+      options: [
+        {
+          excludeArrowFunctions: 'expressionsOnly'
+        }
+      ]
+    },
+    {
+      code: 'function x(foo) {}',
+      errors: [
+        {
+          message: 'Missing "foo" parameter type annotation.'
+        }
+      ],
+      options: [
+        {
+          excludeArrowFunctions: 'expressionsOnly'
+        }
+      ]
+    },
+    {
+      code: '(_foo: number, bar) => {}',
+      errors: [
+        {
+          message: 'Missing "bar" parameter type annotation.'
+        }
+      ],
+      options: [
+        {
+          excludeParameterMatch: '^_'
+        }
+      ]
+    },
+    {
+      code: '(_foo, bar) => {}',
+      errors: [
+        {
+          message: 'Missing "bar" parameter type annotation.'
+        }
+      ],
+      options: [
+        {
+          excludeParameterMatch: '^_'
+        }
+      ]
+    }
+  ],
+  valid: [
+    {
+      code: '(foo: string) => {}'
+    },
+    {
+      code: '(foo: string = \'FOO\') => {}'
+    },
+    {
+      code: '(...foo: string) => {}'
+    },
+    {
+      code: '({foo}: {foo: string}) => {}'
+    },
+    {
+      code: '([foo]: Array) => {}'
+    },
+    {
+      code: '(foo) => {}',
+      settings: {
+        flowtype: {
+          onlyFilesWithFlowAnnotation: true
+        }
+      }
+    },
+    {
+      code: '(foo) => {}',
+      options: [
+        {
+          excludeArrowFunctions: true
+        }
+      ]
+    },
+    {
+      code: '(foo) => 3',
+      options: [
+        {
+          excludeArrowFunctions: 'expressionsOnly'
+        }
+      ]
+    },
+    {
+      code: '(_foo, bar: string) => {}',
+      options: [
+        {
+          excludeParameterMatch: '^_'
+        }
+      ]
+    },
+    {
+      code: '(_foo: number, bar: string) => {}',
+      options: [
+        {
+          excludeParameterMatch: '^_'
+        }
+      ]
+    }
+  ]
+};
diff --git a/tests/rules/assertions/requireReturnType.js b/tests/rules/assertions/requireReturnType.js
new file mode 100644
index 0000000..77c1246
--- /dev/null
+++ b/tests/rules/assertions/requireReturnType.js
@@ -0,0 +1,476 @@
+export default {
+  invalid: [
+    {
+      code: '(foo) => { return "foo"; }',
+      errors: [
+        {
+          message: 'Missing return type annotation.'
+        }
+      ]
+    },
+    {
+      code: '(foo) => { return "foo"; }',
+      errors: [
+        {
+          message: 'Missing return type annotation.'
+        }
+      ],
+      options: [
+        'always'
+      ]
+    },
+    {
+      code: '(foo) => "foo"',
+      errors: [
+        {
+          message: 'Missing return type annotation.'
+        }
+      ],
+      options: [
+        'always'
+      ]
+    },
+    {
+      code: '(foo) => ({})',
+      errors: [
+        {
+          message: 'Missing return type annotation.'
+        }
+      ]
+    },
+    {
+      code: '(foo): undefined => { return; }',
+      errors: [
+        {
+          message: 'Must not annotate undefined return type.'
+        }
+      ]
+    },
+    {
+      code: '(foo): void => { return; }',
+      errors: [
+        {
+          message: 'Must not annotate undefined return type.'
+        }
+      ]
+    },
+    {
+      code: '(foo): undefined => { return undefined; }',
+      errors: [
+        {
+          message: 'Must not annotate undefined return type.'
+        }
+      ]
+    },
+    {
+      code: '(foo): void => { return void 0; }',
+      errors: [
+        {
+          message: 'Must not annotate undefined return type.'
+        }
+      ]
+    },
+    {
+      code: '(foo): undefined => { return; }',
+      errors: [
+        {
+          message: 'Must not annotate undefined return type.'
+        }
+      ],
+      options: [
+        'always',
+        {
+          annotateUndefined: 'never'
+        }
+      ]
+    },
+    {
+      code: '(foo): void => { return; }',
+      errors: [
+        {
+          message: 'Must not annotate undefined return type.'
+        }
+      ],
+      options: [
+        'always',
+        {
+          annotateUndefined: 'never'
+        }
+      ]
+    },
+    {
+      code: '(foo) => { return; }',
+      errors: [
+        {
+          message: 'Must annotate undefined return type.'
+        }
+      ],
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ]
+    },
+    {
+      code: '(foo): undefined => { return undefined; }',
+      errors: [
+        {
+          message: 'Must not annotate undefined return type.'
+        }
+      ],
+      options: [
+        'always',
+        {
+          annotateUndefined: 'never'
+        }
+      ]
+    },
+    {
+      code: '(foo) => { return undefined; }',
+      errors: [
+        {
+          message: 'Must annotate undefined return type.'
+        }
+      ],
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ]
+    },
+    {
+      code: '(foo) => { return void 0; }',
+      errors: [
+        {
+          message: 'Must annotate undefined return type.'
+        }
+      ],
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ]
+    },
+    {
+      code: '// @flow\n(foo) => { return 1; }',
+      errors: [
+        {
+          message: 'Missing return type annotation.'
+        }
+      ],
+      settings: {
+        flowtype: {
+          onlyFilesWithFlowAnnotation: true
+        }
+      }
+    },
+    {
+      code: '// @flow\n (foo) => { return undefined; }',
+      errors: [
+        {
+          message: 'Must annotate undefined return type.'
+        }
+      ],
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ],
+      settings: {
+        flowtype: {
+          onlyFilesWithFlowAnnotation: true
+        }
+      }
+    },
+    {
+      code: 'async () => { return 2; }',
+      errors: [
+        {
+          message: 'Missing return type annotation.'
+        }
+      ],
+      options: [
+        'always'
+      ]
+    },
+    {
+      code: 'async () => {}',
+      errors: [
+        {
+          message: 'Missing return type annotation.'
+        }
+      ],
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ]
+    },
+    {
+      code: 'async function x() {}',
+      errors: [
+        {
+          message: 'Missing return type annotation.'
+        }
+      ],
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ]
+    },
+    {
+      code: 'async () => { return; }',
+      errors: [
+        {
+          message: 'Missing return type annotation.'
+        }
+      ],
+      options: [
+        'always'
+      ]
+    },
+    {
+      code: 'function* x() {}',
+      errors: [
+        {
+          message: 'Missing return type annotation.'
+        }
+      ],
+      options: [
+        'always'
+      ]
+    },
+    {
+      code: '() => { return 3; }',
+      errors: [
+        {
+          message: 'Missing return type annotation.'
+        }
+      ],
+      options: [
+        'always',
+        {
+          excludeArrowFunctions: 'expressionsOnly'
+        }
+      ]
+    },
+    {
+      code: 'async () => { return 4; }',
+      errors: [
+        {
+          message: 'Missing return type annotation.'
+        }
+      ],
+      options: [
+        'always',
+        {
+          excludeArrowFunctions: 'expressionsOnly'
+        }
+      ]
+    }
+  ],
+  valid: [
+    {
+      code: '(foo): string => {}'
+    },
+    {
+      code: '(foo): string => {}',
+      options: [
+        'always'
+      ]
+    },
+    {
+      code: '(foo) => { return; }'
+    },
+    {
+      code: '(foo): Object => ( {} )'
+    },
+    {
+      code: '(foo) => { return undefined; }'
+    },
+    {
+      code: '(foo) => { return void 0; }'
+    },
+    {
+      code: '(foo): undefined => { return; }',
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ]
+    },
+    {
+      code: '(foo): void => { return; }',
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ]
+    },
+    {
+      code: '(foo) => { return; }',
+      options: [
+        'always',
+        {
+          annotateUndefined: 'never'
+        }
+      ]
+    },
+    {
+      code: '(foo) => { return undefined; }',
+      options: [
+        'always',
+        {
+          annotateUndefined: 'never'
+        }
+      ]
+    },
+    {
+      code: '(foo) => { return void 0; }',
+      options: [
+        'always',
+        {
+          annotateUndefined: 'never'
+        }
+      ]
+    },
+    {
+      code: '(foo): undefined => { return undefined; }',
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ]
+    },
+    {
+      code: '(foo): void => { return void 0; }',
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ]
+    },
+    {
+      code: '(foo) => { return 1; }',
+      options: [
+        'always'
+      ],
+      settings: {
+        flowtype: {
+          onlyFilesWithFlowAnnotation: true
+        }
+      }
+    },
+    {
+      code: '(foo) => { return undefined; }',
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ],
+      settings: {
+        flowtype: {
+          onlyFilesWithFlowAnnotation: true
+        }
+      }
+    },
+    {
+      code: 'async function doThing(): Promise<void> {}',
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ]
+    },
+    {
+      code: 'function* doThing(): Generator<number, void, void> { yield 2; }',
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always'
+        }
+      ]
+    },
+    {
+      code: 'async (foo): Promise<number> => { return 3; }'
+    },
+    {
+      code: '() => 3',
+      options: [
+        'always',
+        {
+          excludeArrowFunctions: true
+        }
+      ]
+    },
+    {
+      code: '() => { return 4; }',
+      options: [
+        'always',
+        {
+          excludeArrowFunctions: true
+        }
+      ]
+    },
+    {
+      code: '() => undefined',
+      options: [
+        'always',
+        {
+          excludeArrowFunctions: true
+        }
+      ]
+    },
+    {
+      code: '() => undefined',
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always',
+          excludeArrowFunctions: true
+        }
+      ]
+    },
+    {
+      code: '() => { return undefined; }',
+      options: [
+        'always',
+        {
+          annotateUndefined: 'always',
+          excludeArrowFunctions: true
+        }
+      ]
+    },
+    {
+      code: '() => 3',
+      options: [
+        'always',
+        {
+          excludeArrowFunctions: 'expressionsOnly'
+        }
+      ]
+    },
+    {
+      code: 'async () => 3',
+      options: [
+        'always',
+        {
+          excludeArrowFunctions: 'expressionsOnly'
+        }
+      ]
+    }
+  ]
+};
diff --git a/tests/rules/assertions/requireValidFileAnnotation.js b/tests/rules/assertions/requireValidFileAnnotation.js
new file mode 100644
index 0000000..a47ee38
--- /dev/null
+++ b/tests/rules/assertions/requireValidFileAnnotation.js
@@ -0,0 +1,146 @@
+export default {
+  invalid: [
+    {
+      code: ';// @flow',
+      errors: [
+        {
+          message: 'Flow file annotation not at the top of the file.'
+        }
+      ]
+    },
+    {
+      code: ';\n// @flow',
+      errors: [
+        {
+          message: 'Flow file annotation not at the top of the file.'
+        }
+      ]
+    },
+    {
+      code: '// @Flow',
+      errors: [
+        {
+          message: 'Malformed flow file annotation.'
+        }
+      ]
+    },
+    {
+      code: '// @floweeeeeee',
+      errors: [
+        {
+          message: 'Malformed flow file annotation.'
+        }
+      ]
+    },
+    {
+      code: '// @NoFlow',
+      errors: [
+        {
+          message: 'Malformed flow file annotation.'
+        }
+      ]
+    },
+    {
+      code: '// @nofloweeeeeee',
+      errors: [
+        {
+          message: 'Malformed flow file annotation.'
+        }
+      ]
+    },
+    {
+      code: 'a;',
+      errors: [
+        {
+          message: 'Flow file annotation is missing.'
+        }
+      ],
+      options: [
+        'always'
+      ]
+    },
+    {
+      code: '/* @flow */',
+      errors: [
+        {
+          message: 'Flow file annotation style must be `// @flow`'
+        }
+      ],
+      options: [
+        'always',
+        {
+          annotationStyle: 'line'
+        }
+      ]
+    },
+    {
+      code: '// @flow',
+      errors: [
+        {
+          message: 'Flow file annotation style must be `/* @flow */`'
+        }
+      ],
+      options: [
+        'always',
+        {
+          annotationStyle: 'block'
+        }
+      ]
+    }
+  ],
+  valid: [
+    {
+      code: 'a;'
+    },
+    {
+      code: '// @flow\na;'
+    },
+    {
+      code: '//@flow\na;'
+    },
+    {
+      code: '//**@flow\na;'
+    },
+    {
+      code: '/* foo @flow bar */\na;'
+    },
+    {
+      code: '\n\n// @flow\na;'
+    },
+    {
+      code: '// @flow\n// @FLow'
+    },
+    {
+      code: '// @noflow\na;'
+    },
+    {
+      code: 'a;',
+      options: ['always'],
+      settings: {
+        flowtype: {
+          onlyFilesWithFlowAnnotation: true
+        }
+      }
+    },
+    {
+      code: '// @flow',
+      options: [
+        'always',
+        {
+          annotationStyle: 'line'
+        }
+      ]
+    },
+    {
+      code: '/* @flow */',
+      options: [
+        'always',
+        {
+          annotationStyle: 'block'
+        }
+      ]
+    }
+  ]
+};
+
+
diff --git a/tests/rules/assertions/semi.js b/tests/rules/assertions/semi.js
new file mode 100644
index 0000000..cbb665d
--- /dev/null
+++ b/tests/rules/assertions/semi.js
@@ -0,0 +1,55 @@
+export default {
+  invalid: [
+    {
+      code: 'type FooType = {}',
+      errors: [
+        {
+          message: 'Missing semicolon.'
+        }
+      ],
+      options: [],
+      output: 'type FooType = {};'
+    },
+    {
+      code: 'type FooType = {}',
+      errors: [
+        {
+          message: 'Missing semicolon.'
+        }
+      ],
+      options: ['always'],
+      output: 'type FooType = {};'
+    },
+    {
+      code: 'type FooType = {};',
+      errors: [
+        {
+          message: 'Extra semicolon.'
+        }
+      ],
+      options: ['never'],
+      output: 'type FooType = {}'
+    }
+  ],
+  valid: [
+    {
+      code: 'type FooType = {};'
+    },
+    {
+      code: 'type FooType = {};',
+      options: ['always']
+    },
+    {
+      code: 'type FooType = { a: number;\n b: string;\n };',
+      options: ['always']
+    },
+    {
+      code: 'type FooType = { a: number;\n b: string;\n }',
+      options: ['never']
+    },
+    {
+      code: 'type FooType = {}',
+      options: ['never']
+    }
+  ]
+};
diff --git a/tests/rules/assertions/sortKeys.js b/tests/rules/assertions/sortKeys.js
new file mode 100644
index 0000000..b61754a
--- /dev/null
+++ b/tests/rules/assertions/sortKeys.js
@@ -0,0 +1,84 @@
+export default {
+  invalid: [
+    {
+      code: 'type FooType = { a: number, c: number, b: string }',
+      errors: [{message: 'Expected type annotations to be in ascending order. "b" should be before "c".'}]
+    },
+    {
+      code: 'type FooType = { a: number, b: number, C: number }',
+      errors: [{message: 'Expected type annotations to be in ascending order. "C" should be before "b".'}]
+    },
+    {
+      code: 'type FooType = { 1: number, 2: number, 10: number }',
+      errors: [{message: 'Expected type annotations to be in ascending order. "10" should be before "2".'}]
+    },
+    {
+      code: 'type FooType = { a: number, b: number }',
+      errors: [{message: 'Expected type annotations to be in descending order. "b" should be before "a".'}],
+      options: ['desc']
+    },
+    {
+      code: 'type FooType = { C: number, b: number, a: string }',
+      errors: [{message: 'Expected type annotations to be in descending order. "b" should be before "C".'}],
+      options: ['desc']
+    },
+    {
+      code: 'type FooType = { 10: number, 2: number, 1: number }',
+      errors: [{message: 'Expected type annotations to be in descending order. "2" should be before "10".'}],
+      options: ['desc']
+    },
+    {
+      code: 'type FooType = { a: number, c: number, C: number, b: string }',
+      errors: [{message: 'Expected type annotations to be in insensitive ascending order. "b" should be before "C".'}],
+      options: ['asc', {caseSensitive: false}]
+    },
+    {
+      code: 'type FooType = { a: number, C: number, c: number, b: string }',
+      errors: [{message: 'Expected type annotations to be in insensitive ascending order. "b" should be before "c".'}],
+      options: ['asc', {caseSensitive: false}]
+    },
+    {
+      code: 'type FooType = { 1: number, 10: number, 2: boolean }',
+      errors: [{message: 'Expected type annotations to be in natural ascending order. "2" should be before "10".'}],
+      options: ['asc', {natural: true}]
+    }
+  ],
+  valid: [
+    {
+      code: 'type FooType = { a: number }'
+    },
+    {
+      code: 'type FooType = { a: number, b: number, c: (boolean | number) }'
+    },
+    {
+      code: 'type FooType = { C: number, a: string, b: foo }'
+    },
+    {
+      code: 'type FooType = { 1: number, 10: number, 2: boolean }'
+    },
+    {
+      code: 'type FooType = { c: number, b: number, a: number }',
+      options: ['desc']
+    },
+    {
+      code: 'type FooType = { b: string, a: {}, C: number }',
+      options: ['desc']
+    },
+    {
+      code: 'type FooType = { 2: number, 10: number, 1: boolean }',
+      options: ['desc']
+    },
+    {
+      code: 'type FooType = { a: number, b: number, c: number, C: number }',
+      options: ['asc', {caseSensitive: false}]
+    },
+    {
+      code: 'type FooType = { a: number, b: number, C: number, c: number }',
+      options: ['asc', {caseSensitive: false}]
+    },
+    {
+      code: 'type FooType = { 1:number, 2: number, 10: number }',
+      options: ['asc', {natural: true}]
+    }
+  ]
+};
diff --git a/tests/rules/assertions/spaceAfterTypeColon.js b/tests/rules/assertions/spaceAfterTypeColon.js
new file mode 100644
index 0000000..6ddd35d
--- /dev/null
+++ b/tests/rules/assertions/spaceAfterTypeColon.js
@@ -0,0 +1,1014 @@
+import _ from 'lodash';
+
+const ARROW_FUNCTION_PARAMS = {
+  invalid: [
+    {
+      code: '(foo: string) => {}',
+      errors: [{message: 'There must be no space after "foo" parameter type annotation colon.'}],
+      options: ['never'],
+      output: '(foo:string) => {}'
+    },
+    {
+      code: '(foo:  string) => {}',
+      errors: [{message: 'There must be 1 space after "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: '(foo: string) => {}'
+    },
+    {
+      code: '(foo:(() => void)) => {}',
+      errors: [{message: 'There must be a space after "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: '(foo: (() => void)) => {}'
+    },
+    {
+      code: '(foo: (() => void)) => {}',
+      errors: [{message: 'There must be no space after "foo" parameter type annotation colon.'}],
+      options: ['never'],
+      output: '(foo:(() => void)) => {}'
+    },
+    {
+      code: '(foo:  (() => void)) => {}',
+      errors: [{message: 'There must be 1 space after "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: '(foo: (() => void)) => {}'
+    },
+    {
+      code: '({ lorem, ipsum, dolor } :   SomeType) => {}',
+      errors: [{message: 'There must be 1 space after "{ lorem, ipsum, dolor }" parameter type annotation colon.'}],
+      output: '({ lorem, ipsum, dolor } : SomeType) => {}'
+    },
+    {
+      code: '(foo:{ a: string, b: number }) => {}',
+      errors: [{message: 'There must be a space after "foo" parameter type annotation colon.'}],
+      output: '(foo: { a: string, b: number }) => {}'
+    },
+    {
+      code: '({ a, b } :{ a: string, b: number }) => {}',
+      errors: [{message: 'There must be a space after "{ a, b }" parameter type annotation colon.'}],
+      output: '({ a, b } : { a: string, b: number }) => {}'
+    },
+    {
+      code: '([ a, b ] :string[]) => {}',
+      errors: [{message: 'There must be a space after "[ a, b ]" parameter type annotation colon.'}],
+      output: '([ a, b ] : string[]) => {}'
+    },
+    {
+      code: '(i?:number) => {}',
+      errors: [{message: 'There must be a space after "i" parameter type annotation colon.'}],
+      output: '(i?: number) => {}'
+    },
+    {
+      code: '(i?:  number) => {}',
+      errors: [{message: 'There must be 1 space after "i" parameter type annotation colon.'}],
+      output: '(i?: number) => {}'
+    },
+    {
+      code: '(i?: number) => {}',
+      errors: [{message: 'There must be no space after "i" parameter type annotation colon.'}],
+      options: ['never'],
+      output: '(i?:number) => {}'
+    }
+  ],
+  valid: [
+    {
+      code: '(foo) => {}'
+    },
+    {
+      code: '(foo: string) => {}'
+    },
+    {
+      code: '(foo: (string|number)) => {}'
+    },
+    {
+      code: '(foo:string) => {}',
+      options: ['never']
+    },
+    {
+      code: '(foo: string) => {}',
+      options: ['always']
+    },
+    {
+      code: '(foo:(() => void)) => {}',
+      options: ['never']
+    },
+    {
+      code: '(foo: (() => void)) => {}',
+      options: ['always']
+    },
+    {
+      code: '({ lorem, ipsum, dolor }: SomeType) => {}'
+    },
+    {
+      code: '(foo: { a: string, b: number }) => {}'
+    },
+    {
+      code: '({ a, b }: ?{ a: string, b: number }) => {}'
+    },
+    {
+      code: '([ a, b ]: string[]) => {}'
+    },
+    {
+      code: '(i?: number) => {}'
+    },
+    {
+      code: '(i?:number) => {}',
+      options: ['never']
+    }
+  ]
+};
+
+const ARROW_FUNCTION_RETURN = {
+  invalid: [
+    {
+      code: '():Object => {}',
+      errors: [{message: 'There must be a space after return type colon.'}],
+      options: ['always'],
+      output: '(): Object => {}'
+    },
+    {
+      code: '(): Object => {}',
+      errors: [{message: 'There must be no space after return type colon.'}],
+      options: ['never'],
+      output: '():Object => {}'
+    },
+    {
+      code: '():  Object => {}',
+      errors: [{message: 'There must be 1 space after return type colon.'}],
+      options: ['always'],
+      output: '(): Object => {}'
+    },
+    {
+      code: '():(() => void) => {}',
+      errors: [{message: 'There must be a space after return type colon.'}],
+      options: ['always'],
+      output: '(): (() => void) => {}'
+    },
+    {
+      code: '(): (() => void) => {}',
+      errors: [{message: 'There must be no space after return type colon.'}],
+      options: ['never'],
+      output: '():(() => void) => {}'
+    },
+    {
+      code: '():  (() => void) => {}',
+      errors: [{message: 'There must be 1 space after return type colon.'}],
+      options: ['always'],
+      output: '(): (() => void) => {}'
+    }
+  ],
+  valid: [
+    {
+      code: '():Object => {}',
+      options: ['never']
+    },
+    {
+      code: '(): Object => {}',
+      options: ['always']
+    },
+    {
+      code: '():(number | string) => {}',
+      options: ['never']
+    },
+    {
+      code: '(): (number | string) => {}',
+      options: ['always']
+    },
+    {
+      code: '():number|string => {}',
+      options: ['never']
+    },
+    {
+      code: '(): number|string => {}',
+      options: ['always']
+    },
+    {
+      code: '():(() => void) => {}',
+      options: ['never']
+    },
+    {
+      code: '(): (() => void) => {}',
+      options: ['always']
+    },
+    {
+      code: '():( () => void ) => {}',
+      options: ['never']
+    },
+    {
+      code: '(): ( () => void ) => {}',
+      options: ['always']
+    },
+    {
+      code: '(): { a: number, b: string } => {}'
+    },
+    {
+      code: '() :{ a:number, b:string } => {}',
+      options: ['never']
+    }
+  ]
+};
+
+const FUNCTION_PARAMS = {
+  invalid: [
+    {
+      code: 'export default function (foo: string) {}',
+      errors: [{message: 'There must be no space after "foo" parameter type annotation colon.'}],
+      options: ['never'],
+      output: 'export default function (foo:string) {}'
+    },
+    {
+      code: 'function foo (foo: string) {}',
+      errors: [{message: 'There must be no space after "foo" parameter type annotation colon.'}],
+      options: ['never'],
+      output: 'function foo (foo:string) {}'
+    },
+    {
+      code: '(foo:string) => {}',
+      errors: [{message: 'There must be a space after "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: '(foo: string) => {}'
+    },
+    {
+      code: 'function foo (foo:string) {}',
+      errors: [{message: 'There must be a space after "foo" parameter type annotation colon.'}],
+      output: 'function foo (foo: string) {}'
+    },
+    {
+      code: 'async function foo({ lorem, ipsum, dolor }:SomeType) {}',
+      errors: [{message: 'There must be a space after "{ lorem, ipsum, dolor }" parameter type annotation colon.'}],
+      output: 'async function foo({ lorem, ipsum, dolor }: SomeType) {}'
+    },
+    {
+      code: 'function x(i?:number) {}',
+      errors: [{message: 'There must be a space after "i" parameter type annotation colon.'}],
+      output: 'function x(i?: number) {}'
+    },
+    {
+      code: 'function x(i?:  number) {}',
+      errors: [{message: 'There must be 1 space after "i" parameter type annotation colon.'}],
+      output: 'function x(i?: number) {}'
+    },
+    {
+      code: 'function x(i?: number) {}',
+      errors: [{message: 'There must be no space after "i" parameter type annotation colon.'}],
+      options: ['never'],
+      output: 'function x(i?:number) {}'
+    }
+  ],
+  valid: [
+    {
+      code: 'function x(foo: string) {}'
+    },
+    {
+      code: 'class Foo { constructor(foo: string) {} }'
+    },
+    {
+      code: 'function x(foo:string) {}',
+      options: ['never']
+    },
+    {
+      code: 'class Foo { constructor(foo:string) {} }',
+      options: ['never']
+    },
+    {
+      code: 'async function foo({ lorem, ipsum, dolor }: SomeType) {}'
+    },
+    {
+      code: 'function x({ a, b }: { a: string, b: number }) {}'
+    },
+    {
+      code: 'function x(i?: number) {}'
+    },
+    {
+      code: 'function x(i?:number) {}',
+      options: ['never']
+    }
+  ]
+};
+
+const FUNCTION_RETURN = {
+  invalid: [
+    {
+      code: 'function a():x {}',
+      errors: [{message: 'There must be a space after return type colon.'}],
+      output: 'function a(): x {}'
+    },
+    {
+      code: 'function a():  x {}',
+      errors: [{message: 'There must be 1 space after return type colon.'}],
+      options: ['always'],
+      output: 'function a(): x {}'
+    },
+    {
+      code: 'function a(): x {}',
+      errors: [{message: 'There must be no space after return type colon.'}],
+      options: ['never'],
+      output: 'function a():x {}'
+    }
+  ],
+  valid: [
+    {
+      code: 'function a(): x {}'
+    },
+    {
+      code: 'function a():x {}',
+      options: ['never']
+    },
+    {
+      code: 'function a(): (number | string) {}'
+    },
+    {
+      code: 'function a() :(number | string) {}',
+      options: ['never']
+    }
+  ]
+};
+
+const FUNCTION_TYPE_PARAMS = {
+  invalid: [
+    {
+      code: 'type X = (foo:number) => string',
+      errors: [{message: 'There must be a space after "foo" parameter type annotation colon.'}],
+      output: 'type X = (foo: number) => string'
+    },
+    {
+      code: 'type X = (foo: number) => string',
+      errors: [{message: 'There must be no space after "foo" parameter type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = (foo:number) => string'
+    },
+    {
+      code: 'type X = (foo:  number) => string',
+      errors: [{message: 'There must be 1 space after "foo" parameter type annotation colon.'}],
+      output: 'type X = (foo: number) => string'
+    },
+    {
+      code: 'type X = (foo:?number) => string',
+      errors: [{message: 'There must be a space after "foo" parameter type annotation colon.'}],
+      output: 'type X = (foo: ?number) => string'
+    },
+    {
+      code: 'type X = (foo:(number)) => string',
+      errors: [{message: 'There must be a space after "foo" parameter type annotation colon.'}],
+      output: 'type X = (foo: (number)) => string'
+    },
+    {
+      code: 'type X = (foo:((number))) => string',
+      errors: [{message: 'There must be a space after "foo" parameter type annotation colon.'}],
+      output: 'type X = (foo: ((number))) => string'
+    },
+    {
+      code: 'type X = (foo:  ((number))) => string',
+      errors: [{message: 'There must be 1 space after "foo" parameter type annotation colon.'}],
+      output: 'type X = (foo: ((number))) => string'
+    },
+    {
+      code: 'type X = (foo: ((number))) => string',
+      errors: [{message: 'There must be no space after "foo" parameter type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = (foo:((number))) => string'
+    },
+    {
+      code: 'type X = (foo:?(number)) => string',
+      errors: [{message: 'There must be a space after "foo" parameter type annotation colon.'}],
+      output: 'type X = (foo: ?(number)) => string'
+    },
+    {
+      code: 'type TArrayPredicate = (el: T, i?:number) => boolean',
+      errors: [{message: 'There must be a space after "i" parameter type annotation colon.'}],
+      output: 'type TArrayPredicate = (el: T, i?: number) => boolean'
+    },
+    {
+      code: 'type TArrayPredicate = (el: T, i?:  number) => boolean',
+      errors: [{message: 'There must be 1 space after "i" parameter type annotation colon.'}],
+      output: 'type TArrayPredicate = (el: T, i?: number) => boolean'
+    },
+    {
+      code: 'type TArrayPredicate = (el:T, i?: number) => boolean',
+      errors: [{message: 'There must be no space after "i" parameter type annotation colon.'}],
+      options: ['never'],
+      output: 'type TArrayPredicate = (el:T, i?:number) => boolean'
+    }
+  ],
+  valid: [
+    {
+      code: 'type X = (foo: number) => string;'
+    },
+    {
+      code: 'type X = (foo : number) => string;'
+    },
+    {
+      code: 'type X = (foo: ?number) => string;'
+    },
+    {
+      code: 'type X = (foo? : ?number) => string;'
+    },
+    {
+      code: 'type X = (foo: ?{ x: number }) => string;'
+    },
+    {
+      code: 'type X = (foo:number) => string;',
+      options: ['never']
+    },
+    {
+      code: 'type X = (foo:?{ x:number }) => string;',
+      options: ['never']
+    },
+    {
+      code: 'type X = (foo: (number)) => string'
+    },
+    {
+      code: 'type X = (foo: ((number))) => string'
+    },
+    {
+      code: 'type X = (foo:((number))) => string',
+      options: ['never']
+    },
+    {
+      code: 'type X = ?(foo: ((number))) => string'
+    },
+    {
+      code: 'type X = ?(foo:((number))) => string',
+      options: ['never']
+    },
+    {
+      code: 'type TArrayPredicate = (el: T, i?: number) => boolean'
+    },
+    {
+      code: 'type TArrayPredicate = (el:T, i?:number) => boolean',
+      options: ['never']
+    }
+  ]
+};
+
+const CLASS_PROPERTIES = {
+  invalid: [
+    {
+      code: 'class X { foo:string }',
+      errors: [{message: 'There must be a space after "foo" class property type annotation colon.'}],
+      output: 'class X { foo: string }'
+    },
+    {
+      code: 'class X { foo: string }',
+      errors: [{message: 'There must be no space after "foo" class property type annotation colon.'}],
+      options: ['never'],
+      output: 'class X { foo:string }'
+    },
+    {
+      code: 'class X { foo:?string }',
+      errors: [{message: 'There must be a space after "foo" class property type annotation colon.'}],
+      output: 'class X { foo: ?string }'
+    },
+    {
+      code: 'class X { foo: ?string }',
+      errors: [{message: 'There must be no space after "foo" class property type annotation colon.'}],
+      options: ['never'],
+      output: 'class X { foo:?string }'
+    },
+    {
+      code: 'class X { static foo:number }',
+      errors: [{message: 'There must be a space after "foo" class property type annotation colon.'}],
+      output: 'class X { static foo: number }'
+    },
+    {
+      code: 'class X { static foo: number }',
+      errors: [{message: 'There must be no space after "foo" class property type annotation colon.'}],
+      options: ['never'],
+      output: 'class X { static foo:number }'
+    },
+    {
+      code: 'class X { static foo :number }',
+      errors: [{message: 'There must be a space after "foo" class property type annotation colon.'}],
+      output: 'class X { static foo : number }'
+    },
+    {
+      code: 'class X { static foo : number }',
+      errors: [{message: 'There must be no space after "foo" class property type annotation colon.'}],
+      options: ['never'],
+      output: 'class X { static foo :number }'
+    },
+    {
+      code: 'declare class X { static foo:number }',
+      errors: [{message: 'There must be a space after "foo" type annotation colon.'}],
+      output: 'declare class X { static foo: number }'
+    },
+    {
+      code: 'declare class X { static foo: number }',
+      errors: [{message: 'There must be no space after "foo" type annotation colon.'}],
+      options: ['never'],
+      output: 'declare class X { static foo:number }'
+    },
+    {
+      code: 'declare class X { static foo :number }',
+      errors: [{message: 'There must be a space after "foo" type annotation colon.'}],
+      output: 'declare class X { static foo : number }'
+    },
+    {
+      code: 'declare class X { static foo : number }',
+      errors: [{message: 'There must be no space after "foo" type annotation colon.'}],
+      options: ['never'],
+      output: 'declare class X { static foo :number }'
+    },
+    {
+      code: 'class X { +foo:string }',
+      errors: [{message: 'There must be a space after "foo" class property type annotation colon.'}],
+      output: 'class X { +foo: string }'
+    },
+    {
+      code: 'class X { +foo:  string }',
+      errors: [{message: 'There must be 1 space after "foo" class property type annotation colon.'}],
+      output: 'class X { +foo: string }'
+    },
+    {
+      code: 'class X { +foo: string }',
+      errors: [{message: 'There must be no space after "foo" class property type annotation colon.'}],
+      options: ['never'],
+      output: 'class X { +foo:string }'
+    },
+    {
+      code: 'class X { static +foo:string }',
+      errors: [{message: 'There must be a space after "foo" class property type annotation colon.'}],
+      output: 'class X { static +foo: string }'
+    },
+    {
+      code: 'class X { static +foo:  string }',
+      errors: [{message: 'There must be 1 space after "foo" class property type annotation colon.'}],
+      output: 'class X { static +foo: string }'
+    },
+    {
+      code: 'class X { static +foo: string }',
+      errors: [{message: 'There must be no space after "foo" class property type annotation colon.'}],
+      options: ['never'],
+      output: 'class X { static +foo:string }'
+    }
+  ],
+  valid: [
+    {
+      code: 'class Foo { bar }'
+    },
+    {
+      code: 'class Foo { bar = 3 }'
+    },
+    {
+      code: 'class Foo { bar: string }'
+    },
+    {
+      code: 'class Foo { bar: ?string }'
+    },
+    {
+      code: 'class Foo { bar:string }',
+      options: ['never']
+    },
+    {
+      code: 'class Foo { bar:?string }',
+      options: ['never']
+    },
+    {
+      code: 'class X { static foo : number }'
+    },
+    {
+      code: 'class X { static foo :number }',
+      options: ['never']
+    },
+    {
+      code: 'declare class X { static foo : number }'
+    },
+    {
+      code: 'declare class X { static foo :number }',
+      options: ['never']
+    },
+    {
+      code: 'class X { +foo: string }'
+    },
+    {
+      code: 'class X { static +foo: string }'
+    },
+    {
+      code: 'class X { +foo:string }',
+      options: ['never']
+    },
+    {
+      code: 'class X { static +foo:string }',
+      options: ['never']
+    }
+  ]
+};
+
+const OBJECT_TYPE_PROPERTIES = {
+  invalid: [
+    {
+      code: 'type X = { foo:string }',
+      errors: [{message: 'There must be a space after "foo" type annotation colon.'}],
+      output: 'type X = { foo: string }'
+    },
+    {
+      code: 'type X = { foo:string }',
+      errors: [{message: 'There must be a space after "foo" type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { foo: string }'
+    },
+    {
+      code: 'type X = { foo: string }',
+      errors: [{message: 'There must be no space after "foo" type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { foo:string }'
+    },
+    {
+      code: 'type X = { foo:  string }',
+      errors: [{message: 'There must be 1 space after "foo" type annotation colon.'}],
+      output: 'type X = { foo: string }'
+    },
+    {
+      code: 'type X = { foo?:string }',
+      errors: [{message: 'There must be a space after "foo" type annotation colon.'}],
+      output: 'type X = { foo?: string }'
+    },
+    {
+      code: 'type X = { foo?: string }',
+      errors: [{message: 'There must be no space after "foo" type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { foo?:string }'
+    },
+    {
+      code: 'type X = { foo?:?string }',
+      errors: [{message: 'There must be a space after "foo" type annotation colon.'}],
+      output: 'type X = { foo?: ?string }'
+    },
+    {
+      code: 'type X = { foo?:  ?string }',
+      errors: [{message: 'There must be 1 space after "foo" type annotation colon.'}],
+      output: 'type X = { foo?: ?string }'
+    },
+    {
+      code: 'type Foo = { barType:(string | () => void) }',
+      errors: [{message: 'There must be a space after "barType" type annotation colon.'}],
+      output: 'type Foo = { barType: (string | () => void) }'
+    },
+    {
+      code: 'type Foo = { barType:(((string | () => void))) }',
+      errors: [{message: 'There must be a space after "barType" type annotation colon.'}],
+      output: 'type Foo = { barType: (((string | () => void))) }'
+    },
+    {
+      code: 'type Foo = { barType: (string | () => void) }',
+      errors: [{message: 'There must be no space after "barType" type annotation colon.'}],
+      options: ['never'],
+      output: 'type Foo = { barType:(string | () => void) }'
+    },
+    {
+      code: 'type Foo = { barType:  (string | () => void) }',
+      errors: [{message: 'There must be 1 space after "barType" type annotation colon.'}],
+      output: 'type Foo = { barType: (string | () => void) }'
+    },
+    {
+      code: 'type Foo = { barType:  ((string | () => void)) }',
+      errors: [{message: 'There must be 1 space after "barType" type annotation colon.'}],
+      output: 'type Foo = { barType: ((string | () => void)) }'
+    },
+    {
+      code: 'type X = { get:() => A; }',
+      errors: [{message: 'There must be a space after "get" type annotation colon.'}],
+      output: 'type X = { get: () => A; }'
+    },
+    {
+      code: 'type X = { get:<X>() => A; }',
+      errors: [{message: 'There must be a space after "get" type annotation colon.'}],
+      output: 'type X = { get: <X>() => A; }'
+    },
+    {
+      code: 'type X = { get: () => A; }',
+      errors: [{message: 'There must be no space after "get" type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { get:() => A; }'
+    },
+    {
+      code: 'type X = { get: <X>() => A; }',
+      errors: [{message: 'There must be no space after "get" type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { get:<X>() => A; }'
+    },
+    {
+      code: 'type X = { get:  () => A; }',
+      errors: [{message: 'There must be 1 space after "get" type annotation colon.'}],
+      output: 'type X = { get: () => A; }'
+    },
+    {
+      code: 'type X = { get:  <X>() => A; }',
+      errors: [{message: 'There must be 1 space after "get" type annotation colon.'}],
+      output: 'type X = { get: <X>() => A; }'
+    },
+    {
+      code: 'type X = { +foo:string }',
+      errors: [{message: 'There must be a space after "foo" type annotation colon.'}],
+      output: 'type X = { +foo: string }'
+    },
+    {
+      code: 'type X = { +foo:  string }',
+      errors: [{message: 'There must be 1 space after "foo" type annotation colon.'}],
+      output: 'type X = { +foo: string }'
+    },
+    {
+      code: 'type X = { +foo: string }',
+      errors: [{message: 'There must be no space after "foo" type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { +foo:string }'
+    },
+    {
+      code: 'type X = { +foo?:string }',
+      errors: [{message: 'There must be a space after "foo" type annotation colon.'}],
+      output: 'type X = { +foo?: string }'
+    },
+    {
+      code: 'type X = { +foo?:  string }',
+      errors: [{message: 'There must be 1 space after "foo" type annotation colon.'}],
+      output: 'type X = { +foo?: string }'
+    },
+    {
+      code: 'type X = { +foo?: string }',
+      errors: [{message: 'There must be no space after "foo" type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { +foo?:string }'
+    }
+  ],
+  valid: [
+    {
+      code: 'type X = { foo: string }'
+    },
+    {
+      code: 'type X = { foo:string }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { foo?: string }'
+    },
+    {
+      code: 'type X = { foo?: ?string }'
+    },
+    {
+      code: 'type X = { foo?:?string }',
+      options: ['never']
+    },
+    {
+      code: 'type Foo = { barType: (string | () => void) }'
+    },
+    {
+      code: 'type Foo = { barType: ((string | () => void)) }'
+    },
+    {
+      code: 'type Foo = { barType:(string | () => void) }',
+      options: ['never']
+    },
+    {
+      code: 'type Foo = { barType:((string | () => void)) }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { get(): A; }'
+    },
+    {
+      code: 'type X = { get<X>(): A; }'
+    },
+    {
+      code: 'type X = { get(): A; }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { get<X>(): A; }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { get: () => A; }'
+    },
+    {
+      code: 'type X = { get: <X>() => A; }'
+    },
+    {
+      code: 'type X = { get:() => A; }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { get:<X>() => A; }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { +foo: string }'
+    },
+    {
+      code: 'type X = { +foo?: string }'
+    },
+    {
+      code: 'type X = { +foo:string }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { +foo?:string }',
+      options: ['never']
+    }
+  ]
+};
+
+
+const OBJECT_TYPE_INDEXERS = {
+  invalid: [
+    // [id:key]: value
+    //    ^
+    {
+      code: 'type X = { [a:b]: c }',
+      errors: [{message: 'There must be a space after type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { [a: b]: c }'
+    },
+    {
+      code: 'type X = { [a: b]:c }',
+      errors: [{message: 'There must be no space after type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { [a:b]:c }'
+    },
+    {
+      code: 'type X = { [a:    b]: c }',
+      errors: [{message: 'There must be 1 space after type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { [a: b]: c }'
+    },
+    {
+      code: 'type X = { +[a:b]: c }',
+      errors: [{message: 'There must be a space after type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { +[a: b]: c }'
+    },
+    {
+      code: 'type X = { +[a: b]:c }',
+      errors: [{message: 'There must be no space after type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { +[a:b]:c }'
+    },
+    {
+      code: 'type X = { +[a:    b]: c }',
+      errors: [{message: 'There must be 1 space after type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { +[a: b]: c }'
+    },
+    // [id:key]: value
+    //         ^
+    {
+      code: 'type X = { [a: b]:c }',
+      errors: [{message: 'There must be a space after type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { [a: b]: c }'
+    },
+    {
+      code: 'type X = { [a:b]: c }',
+      errors: [{message: 'There must be no space after type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { [a:b]:c }'
+    },
+    {
+      code: 'type X = { [a: b]:    c }',
+      errors: [{message: 'There must be 1 space after type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { [a: b]: c }'
+    },
+    // [id:key]: value
+    //    ^    ^
+    {
+      code: 'type X = { [a:b]:c }',
+      errors: [
+        {message: 'There must be a space after type annotation colon.'},
+        {message: 'There must be a space after type annotation colon.'}
+      ],
+      options: ['always'],
+      output: 'type X = { [a: b]: c }'
+    },
+    {
+      code: 'type X = { [a: b]: c }',
+      errors: [
+        {message: 'There must be no space after type annotation colon.'},
+        {message: 'There must be no space after type annotation colon.'}
+      ],
+      options: ['never'],
+      output: 'type X = { [a:b]:c }'
+    },
+    {
+      code: 'type X = { [a:  b]:  c }',
+      errors: [
+        {message: 'There must be 1 space after type annotation colon.'},
+        {message: 'There must be 1 space after type annotation colon.'}
+      ],
+      options: ['always'],
+      output: 'type X = { [a: b]: c }'
+    },
+    {
+      code: 'type X = { [a:(b)]:(c) }',
+      errors: [
+        {message: 'There must be a space after type annotation colon.'},
+        {message: 'There must be a space after type annotation colon.'}
+      ],
+      options: ['always'],
+      output: 'type X = { [a: (b)]: (c) }'
+    },
+    {
+      code: 'type X = { [a: (b)]: (c) }',
+      errors: [
+        {message: 'There must be no space after type annotation colon.'},
+        {message: 'There must be no space after type annotation colon.'}
+      ],
+      options: ['never'],
+      output: 'type X = { [a:(b)]:(c) }'
+    }
+  ],
+  valid: [
+    {
+      code: 'type X = { [a: b]: c }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { [a:b]:c }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { +[a: b]: c }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { +[a:b]:c }',
+      options: ['never']
+    }
+  ]
+};
+
+
+const TYPE_CAST_EXPRESSIONS = {
+  invalid: [
+    {
+      code: 'const x = ({}: {})',
+      errors: [{message: 'There must be no space after type cast colon.'}],
+      options: ['never'],
+      output: 'const x = ({}:{})'
+    },
+    {
+      code: 'const x = ({}:{})',
+      errors: [{message: 'There must be a space after type cast colon.'}],
+      options: ['always'],
+      output: 'const x = ({}: {})'
+    },
+    {
+      code: 'const x = ({}:  {})',
+      errors: [{message: 'There must be 1 space after type cast colon.'}],
+      options: ['always'],
+      output: 'const x = ({}: {})'
+    },
+    {
+      code: '((x): (string))',
+      errors: [{message: 'There must be no space after type cast colon.'}],
+      options: ['never'],
+      output: '((x):(string))'
+    },
+    {
+      code: '((x):(string))',
+      errors: [{message: 'There must be a space after type cast colon.'}],
+      options: ['always'],
+      output: '((x): (string))'
+    },
+    {
+      code: '((x):  (string))',
+      errors: [{message: 'There must be 1 space after type cast colon.'}],
+      options: ['always'],
+      output: '((x): (string))'
+    }
+  ],
+  valid: [
+    {
+      code: 'const x = ({}:{})',
+      options: ['never']
+    },
+    {
+      code: 'const x = ({}: {})',
+      options: ['always']
+    },
+    {
+      code: '((x):(string))',
+      options: ['never']
+    },
+    {
+      code: '((x): (string))',
+      options: ['always']
+    }
+  ]
+};
+
+
+const ALL = [
+  ARROW_FUNCTION_PARAMS,
+  ARROW_FUNCTION_RETURN,
+  FUNCTION_PARAMS,
+  FUNCTION_RETURN,
+  FUNCTION_TYPE_PARAMS,
+  CLASS_PROPERTIES,
+  OBJECT_TYPE_PROPERTIES,
+  OBJECT_TYPE_INDEXERS,
+  TYPE_CAST_EXPRESSIONS
+];
+
+export default {
+  invalid: _.flatMap(ALL, (rules) => { return rules.invalid; }),
+  valid: _.flatMap(ALL, (rules) => { return rules.valid; })
+};
diff --git a/tests/rules/assertions/spaceBeforeGenericBracket.js b/tests/rules/assertions/spaceBeforeGenericBracket.js
new file mode 100644
index 0000000..d25bbf2
--- /dev/null
+++ b/tests/rules/assertions/spaceBeforeGenericBracket.js
@@ -0,0 +1,41 @@
+export default {
+  invalid: [
+    {
+      code: 'type X = Promise <string>',
+      errors: [{message: 'There must be no space before "Promise" generic type annotation bracket'}],
+      output: 'type X = Promise<string>'
+    },
+    {
+      code: 'type X = Promise <string>',
+      errors: [{message: 'There must be no space before "Promise" generic type annotation bracket'}],
+      options: ['never'],
+      output: 'type X = Promise<string>'
+    },
+    {
+      code: 'type X = Promise  <string>',
+      errors: [{message: 'There must be no space before "Promise" generic type annotation bracket'}],
+      output: 'type X = Promise<string>'
+    },
+    {
+      code: 'type X = Promise<string>',
+      errors: [{message: 'There must be a space before "Promise" generic type annotation bracket'}],
+      options: ['always'],
+      output: 'type X = Promise <string>'
+    },
+    {
+      code: 'type X = Promise  <string>',
+      errors: [{message: 'There must be one space before "Promise" generic type annotation bracket'}],
+      options: ['always'],
+      output: 'type X = Promise <string>'
+    }
+  ],
+  valid: [
+    {
+      code: 'type X = Promise<string>'
+    },
+    {
+      code: 'type X = Promise <string>',
+      options: ['always']
+    }
+  ]
+};
diff --git a/tests/rules/assertions/spaceBeforeTypeColon.js b/tests/rules/assertions/spaceBeforeTypeColon.js
new file mode 100644
index 0000000..aa1fe02
--- /dev/null
+++ b/tests/rules/assertions/spaceBeforeTypeColon.js
@@ -0,0 +1,845 @@
+import _ from 'lodash';
+
+const ARROW_FUNCTION_PARAMS = {
+  invalid: [
+    {
+      code: '(foo : string) => {}',
+      errors: [{message: 'There must be no space before "foo" parameter type annotation colon.'}],
+      options: ['never'],
+      output: '(foo: string) => {}'
+    },
+    {
+      code: '(foo ? : string) => {}',
+      errors: [{message: 'There must be no space before "foo" parameter type annotation colon.'}],
+      options: ['never'],
+      output: '(foo ?: string) => {}'
+    },
+    {
+      code: '(foo: string) => {}',
+      errors: [{message: 'There must be a space before "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: '(foo : string) => {}'
+    },
+    {
+      code: '(foo  : string) => {}',
+      errors: [{message: 'There must be 1 space before "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: '(foo : string) => {}'
+    },
+    {
+      code: '(foo?: string) => {}',
+      errors: [{message: 'There must be a space before "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: '(foo? : string) => {}'
+    },
+    {
+      code: '(foo ?  : string) => {}',
+      errors: [{message: 'There must be 1 space before "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: '(foo ? : string) => {}'
+    },
+    {
+      code: '(foo  ?: string) => {}',
+      errors: [{message: 'There must be a space before "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: '(foo  ? : string) => {}'
+    },
+    {
+      code: '({ lorem, ipsum, dolor } : SomeType) => {}',
+      errors: [{message: 'There must be no space before "{ lorem, ipsum, dolor }" parameter type annotation colon.'}],
+      output: '({ lorem, ipsum, dolor }: SomeType) => {}'
+    },
+    {
+      code: '(foo : { a: string, b: number }) => {}',
+      errors: [{message: 'There must be no space before "foo" parameter type annotation colon.'}],
+      output: '(foo: { a: string, b: number }) => {}'
+    },
+    {
+      code: '({ a, b } : { a: string, b: number }) => {}',
+      errors: [{message: 'There must be no space before "{ a, b }" parameter type annotation colon.'}],
+      output: '({ a, b }: { a: string, b: number }) => {}'
+    },
+    {
+      code: '([ a, b ] : string[]) => {}',
+      errors: [{message: 'There must be no space before "[ a, b ]" parameter type annotation colon.'}],
+      output: '([ a, b ]: string[]) => {}'
+    }
+  ],
+  valid: [
+    {
+      code: '(foo) => {}'
+    },
+    {
+      code: '(foo: string) => {}'
+    },
+    {
+      code: '(foo?: string) => {}'
+    },
+    {
+      code: '(foo ?: string) => {}'
+    },
+    {
+      code: '(foo: string) => {}',
+      options: ['never']
+    },
+    {
+      code: '(foo : string) => {}',
+      options: ['always']
+    },
+    {
+      code: '(foo? : string) => {}',
+      options: ['always']
+    },
+    {
+      code: '(foo ? : string) => {}',
+      options: ['always']
+    },
+    {
+      code: '(foo  ? : string) => {}',
+      options: ['always']
+    },
+    {
+      code: '({ lorem, ipsum, dolor }: SomeType) => {}'
+    },
+    {
+      code: '(foo: { a: string, b: number }) => {}'
+    },
+    {
+      code: '({ a, b }: ?{ a: string, b: number }) => {}'
+    },
+    {
+      code: '(): { a: number, b: string } => {}'
+    },
+    {
+      code: '() : { a : number, b : string } => {}',
+      options: ['always']
+    },
+    {
+      code: '([ a, b ]: string[]) => {}'
+    }
+  ]
+};
+
+const ARROW_FUNCTION_RETURN = {
+  invalid: [
+    {
+      code: '() : x => {}',
+      errors: [{message: 'There must be no space before return type colon.'}],
+      output: '(): x => {}'
+    },
+    {
+      code: '(): x => {}',
+      errors: [{message: 'There must be a space before return type colon.'}],
+      options: ['always'],
+      output: '() : x => {}'
+    },
+    {
+      code: '()  : x => {}',
+      errors: [{message: 'There must be 1 space before return type colon.'}],
+      options: ['always'],
+      output: '() : x => {}'
+    }
+  ],
+  valid: [
+    {
+      code: '(): x => {}'
+    },
+    {
+      code: '() : x => {}',
+      options: ['always']
+    },
+    {
+      code: '(): (number | string) => {}'
+    },
+    {
+      code: '() : (number | string) => {}',
+      options: ['always']
+    }
+  ]
+};
+
+const FUNCTION_PARAMS = {
+  invalid: [
+    {
+      code: 'function x(foo : string) {}',
+      errors: [{message: 'There must be no space before "foo" parameter type annotation colon.'}],
+      output: 'function x(foo: string) {}'
+    },
+    {
+      code: 'function x(foo: string) {}',
+      errors: [{message: 'There must be a space before "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: 'function x(foo : string) {}'
+    },
+    {
+      code: 'var x = function (foo : string) {}',
+      errors: [{message: 'There must be no space before "foo" parameter type annotation colon.'}],
+      output: 'var x = function (foo: string) {}'
+    },
+    {
+      code: 'var x = function (foo: string) {}',
+      errors: [{message: 'There must be a space before "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: 'var x = function (foo : string) {}'
+    },
+    {
+      code: 'class Foo { constructor(foo : string ) {} }',
+      errors: [{message: 'There must be no space before "foo" parameter type annotation colon.'}],
+      output: 'class Foo { constructor(foo: string ) {} }'
+    },
+    {
+      code: 'class Foo { constructor(foo: string ) {} }',
+      errors: [{message: 'There must be a space before "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: 'class Foo { constructor(foo : string ) {} }'
+    },
+    {
+      code: 'async function foo({ lorem, ipsum, dolor } : SomeType) {}',
+      errors: [{message: 'There must be no space before "{ lorem, ipsum, dolor }" parameter type annotation colon.'}],
+      output: 'async function foo({ lorem, ipsum, dolor }: SomeType) {}'
+    }
+  ],
+  valid: [
+    {
+      code: 'function x(foo: string) {}'
+    },
+    {
+      code: 'function x(foo : string) {}',
+      options: ['always']
+    },
+    {
+      code: 'var x = function (foo: string) {}'
+    },
+    {
+      code: 'var x = function (foo : string) {}',
+      options: ['always']
+    },
+    {
+      code: 'class X { foo({ bar }: Props = this.props) {} }'
+    },
+    {
+      code: 'class Foo { constructor(foo: string ) {} }'
+    },
+    {
+      code: 'class Foo { constructor(foo : string ) {} }',
+      options: ['always']
+    },
+    {
+      code: 'async function foo({ lorem, ipsum, dolor }: SomeType) {}'
+    },
+    {
+      code: 'function x({ a, b }: { a: string, b: number }) {}'
+    }
+  ]
+};
+
+const FUNCTION_RETURN = {
+  invalid: [
+    {
+      code: 'function a() : x {}',
+      errors: [{message: 'There must be no space before return type colon.'}],
+      output: 'function a(): x {}'
+    },
+    {
+      code: 'function a(): x {}',
+      errors: [{message: 'There must be a space before return type colon.'}],
+      options: ['always'],
+      output: 'function a() : x {}'
+    },
+    {
+      code: 'function a()  : x {}',
+      errors: [{message: 'There must be 1 space before return type colon.'}],
+      options: ['always'],
+      output: 'function a() : x {}'
+    }
+  ],
+  valid: [
+    {
+      code: 'function a(): x {}'
+    },
+    {
+      code: 'function a() : x {}',
+      options: ['always']
+    },
+    {
+      code: 'function a(): (number | string) {}'
+    },
+    {
+      code: 'function a() : (number | string) {}',
+      options: ['always']
+    }
+  ]
+};
+
+const FUNCTION_TYPE_PARAMS = {
+  invalid: [
+    {
+      code: 'type X = (foo :string) => string;',
+      errors: [{message: 'There must be no space before "foo" parameter type annotation colon.'}],
+      output: 'type X = (foo:string) => string;'
+    },
+    {
+      code: 'type X = (foo:string) => string;',
+      errors: [{message: 'There must be a space before "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = (foo :string) => string;'
+    },
+    {
+      code: 'type X = (foo  :string) => string;',
+      errors: [{message: 'There must be 1 space before "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = (foo :string) => string;'
+    },
+    {
+      code: 'type X = (foo? :string) => string;',
+      errors: [{message: 'There must be no space before "foo" parameter type annotation colon.'}],
+      output: 'type X = (foo?:string) => string;'
+    },
+    {
+      code: 'type X = (foo?     :string) => string;',
+      errors: [{message: 'There must be no space before "foo" parameter type annotation colon.'}],
+      output: 'type X = (foo?:string) => string;'
+    },
+    {
+      code: 'type X = (foo?:string) => string;',
+      errors: [{message: 'There must be a space before "foo" parameter type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = (foo? :string) => string;'
+    },
+    {
+      code: 'type X = (foo? :?string) => string;',
+      errors: [{message: 'There must be no space before "foo" parameter type annotation colon.'}],
+      output: 'type X = (foo?:?string) => string;'
+    }
+  ],
+  valid: [
+    {
+      code: 'type X = (foo:string) => number;'
+    },
+    {
+      code: 'type X = (foo: string) => number;'
+    },
+    {
+      code: 'type X = (foo: ?string) => number;'
+    },
+    {
+      code: 'type X = (foo?: string) => number;'
+    },
+    {
+      code: 'type X = (foo?: ?string) => number;'
+    },
+    {
+      code: 'type X = (foo   ?: string) => number;'
+    },
+    {
+      code: 'type X = (foo? : string) => number',
+      options: ['always']
+    },
+    {
+      code: 'type X = (foo? : ?string) => number',
+      options: ['always']
+    }
+  ]
+};
+
+const CLASS_PROPERTIES = {
+  invalid: [
+    {
+      code: 'class X { foo :string }',
+      errors: [{message: 'There must be no space before "foo" class property type annotation colon.'}],
+      output: 'class X { foo:string }'
+    },
+    {
+      code: 'class X { foo: string }',
+      errors: [{message: 'There must be a space before "foo" class property type annotation colon.'}],
+      options: ['always'],
+      output: 'class X { foo : string }'
+    },
+    {
+      code: 'class X { foo :?string }',
+      errors: [{message: 'There must be no space before "foo" class property type annotation colon.'}],
+      output: 'class X { foo:?string }'
+    },
+    {
+      code: 'class X { foo: ?string }',
+      errors: [{message: 'There must be a space before "foo" class property type annotation colon.'}],
+      options: ['always'],
+      output: 'class X { foo : ?string }'
+    },
+    {
+      code: 'class X { static foo : number }',
+      errors: [{message: 'There must be no space before "foo" class property type annotation colon.'}],
+      output: 'class X { static foo: number }'
+    },
+    {
+      code: 'class X { static foo :number }',
+      errors: [{message: 'There must be no space before "foo" class property type annotation colon.'}],
+      output: 'class X { static foo:number }'
+    },
+    {
+      code: 'class X { static foo: number }',
+      errors: [{message: 'There must be a space before "foo" class property type annotation colon.'}],
+      options: ['always'],
+      output: 'class X { static foo : number }'
+    },
+    {
+      code: 'class X { static foo:number }',
+      errors: [{message: 'There must be a space before "foo" class property type annotation colon.'}],
+      options: ['always'],
+      output: 'class X { static foo :number }'
+    },
+    {
+      code: 'declare class Foo { static bar :number; }',
+      errors: [{message: 'There must be no space before "bar" type annotation colon.'}],
+      output: 'declare class Foo { static bar:number; }'
+    },
+    {
+      code: 'declare class Foo { static bar : number; }',
+      errors: [{message: 'There must be no space before "bar" type annotation colon.'}],
+      output: 'declare class Foo { static bar: number; }'
+    },
+    {
+      code: 'declare class Foo { static bar:number; }',
+      errors: [{message: 'There must be a space before "bar" type annotation colon.'}],
+      options: ['always'],
+      output: 'declare class Foo { static bar :number; }'
+    },
+    {
+      code: 'declare class Foo { static bar: number; }',
+      errors: [{message: 'There must be a space before "bar" type annotation colon.'}],
+      options: ['always'],
+      output: 'declare class Foo { static bar : number; }'
+    },
+    {
+      code: 'class X { +foo: string }',
+      errors: [{message: 'There must be a space before "foo" class property type annotation colon.'}],
+      options: ['always'],
+      output: 'class X { +foo : string }'
+    },
+    {
+      code: 'class X { +foo  : string }',
+      errors: [{message: 'There must be 1 space before "foo" class property type annotation colon.'}],
+      options: ['always'],
+      output: 'class X { +foo : string }'
+    },
+    {
+      code: 'class X { +foo : string }',
+      errors: [{message: 'There must be no space before "foo" class property type annotation colon.'}],
+      options: ['never'],
+      output: 'class X { +foo: string }'
+    },
+    {
+      code: 'class X { static +foo: string }',
+      errors: [{message: 'There must be a space before "foo" class property type annotation colon.'}],
+      options: ['always'],
+      output: 'class X { static +foo : string }'
+    },
+    {
+      code: 'class X { static +foo  : string }',
+      errors: [{message: 'There must be 1 space before "foo" class property type annotation colon.'}],
+      options: ['always'],
+      output: 'class X { static +foo : string }'
+    },
+    {
+      code: 'class X { static +foo : string }',
+      errors: [{message: 'There must be no space before "foo" class property type annotation colon.'}],
+      options: ['never'],
+      output: 'class X { static +foo: string }'
+    }
+  ],
+  valid: [
+    {
+      code: 'class Foo { bar }'
+    },
+    {
+      code: 'class Foo { bar = 3 }'
+    },
+    {
+      code: 'class Foo { bar: string }'
+    },
+    {
+      code: 'class Foo { bar: ?string }'
+    },
+    {
+      code: 'class Foo { bar:?string }'
+    },
+    {
+      code: 'class Foo { bar : string }',
+      options: ['always']
+    },
+    {
+      code: 'class X { static foo:number }'
+    },
+    {
+      code: 'class X { static foo: number }'
+    },
+    {
+      code: 'class X { static foo :number }',
+      options: ['always']
+    },
+    {
+      code: 'class X { static foo : number }',
+      options: ['always']
+    },
+    {
+      code: 'declare class Foo { static bar:number; }'
+    },
+    {
+      code: 'declare class Foo { static bar :number; }',
+      options: ['always']
+    },
+    {
+      code: 'declare class Foo { static bar: number; }'
+    },
+    {
+      code: 'declare class Foo { static bar : number; }',
+      options: ['always']
+    },
+    {
+      code: 'class X { +foo: string }'
+    },
+    {
+      code: 'class X { static +foo: string }'
+    },
+    {
+      code: 'class X { +foo : string }',
+      options: ['always']
+    },
+    {
+      code: 'class X { static +foo : string }',
+      options: ['always']
+    }
+  ]
+};
+
+const OBJECT_TYPE_PROPERTIES = {
+  invalid: [
+    {
+      code: 'type X = { foo : string }',
+      errors: [{message: 'There must be no space before "foo" type annotation colon.'}],
+      output: 'type X = { foo: string }'
+    },
+    {
+      code: 'type X = { foo : string }',
+      errors: [{message: 'There must be no space before "foo" type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { foo: string }'
+    },
+    {
+      code: 'type X = { foo: string }',
+      errors: [{message: 'There must be a space before "foo" type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { foo : string }'
+    },
+    {
+      code: 'type X = { foo  : string }',
+      errors: [{message: 'There must be 1 space before "foo" type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { foo : string }'
+    },
+    {
+      code: 'type X = { foo? : string }',
+      errors: [{message: 'There must be no space before "foo" type annotation colon.'}],
+      output: 'type X = { foo?: string }'
+    },
+    {
+      code: 'type X = { foo?: string }',
+      errors: [{message: 'There must be a space before "foo" type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { foo? : string }'
+    },
+    {
+      code: 'type X = { foo?  : string }',
+      errors: [{message: 'There must be 1 space before "foo" type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { foo? : string }'
+    },
+    {
+      code: 'type X = { foo   ?: string }',
+      errors: [{message: 'There must be a space before "foo" type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { foo   ? : string }'
+    },
+    {
+      code: 'type X = { +foo: string }',
+      errors: [{message: 'There must be a space before "foo" type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { +foo : string }'
+    },
+    {
+      code: 'type X = { +foo  : string }',
+      errors: [{message: 'There must be 1 space before "foo" type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { +foo : string }'
+    },
+    {
+      code: 'type X = { +foo : string }',
+      errors: [{message: 'There must be no space before "foo" type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { +foo: string }'
+    },
+    {
+      code: 'type X = { +foo?: string }',
+      errors: [{message: 'There must be a space before "foo" type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { +foo? : string }'
+    },
+    {
+      code: 'type X = { +foo?  : string }',
+      errors: [{message: 'There must be 1 space before "foo" type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { +foo? : string }'
+    },
+    {
+      code: 'type X = { +foo? : string }',
+      errors: [{message: 'There must be no space before "foo" type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { +foo?: string }'
+    }
+  ],
+  valid: [
+    {
+      code: 'type X = { foo: string }'
+    },
+    {
+      code: 'type X = { foo : string }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { foo?: string }'
+    },
+    {
+      code: 'type X = { foo   ?: string }'
+    },
+    {
+      code: 'type X = { foo? : string }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { +foo: string }'
+    },
+    {
+      code: 'type X = { +foo?: string }'
+    },
+    {
+      code: 'type X = { +foo : string }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { +foo? : string }',
+      options: ['always']
+    }
+  ]
+};
+
+const OBJECT_TYPE_INDEXERS = {
+  invalid: [
+    // [id:key]: value
+    //    ^
+    {
+      code: 'type X = { [a: b] : c }',
+      errors: [{message: 'There must be a space before type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { [a : b] : c }'
+    },
+    {
+      code: 'type X = { [a : b]: c }',
+      errors: [{message: 'There must be no space before type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { [a: b]: c }'
+    },
+    {
+      code: 'type X = { [a  : b] : c }',
+      errors: [{message: 'There must be 1 space before type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { [a : b] : c }'
+    },
+    {
+      code: 'type X = { +[a:b] : c }',
+      errors: [{message: 'There must be a space before type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { +[a :b] : c }'
+    },
+    {
+      code: 'type X = { +[a : b]: c }',
+      errors: [{message: 'There must be no space before type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { +[a: b]: c }'
+    },
+    {
+      code: 'type X = { +[a  : b] : c }',
+      errors: [{message: 'There must be 1 space before type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { +[a : b] : c }'
+    },
+    // [id:key]: value
+    //         ^
+    {
+      code: 'type X = { [a : b]: c }',
+      errors: [{message: 'There must be a space before type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { [a : b] : c }'
+    },
+    {
+      code: 'type X = { [a: b] : c }',
+      errors: [{message: 'There must be no space before type annotation colon.'}],
+      options: ['never'],
+      output: 'type X = { [a: b]: c }'
+    },
+    {
+      code: 'type X = { [a : b]  : c }',
+      errors: [{message: 'There must be 1 space before type annotation colon.'}],
+      options: ['always'],
+      output: 'type X = { [a : b] : c }'
+    },
+    // [id:key]: value
+    //    ^    ^
+    {
+      code: 'type X = { [a:b]:c }',
+      errors: [
+        {message: 'There must be a space before type annotation colon.'},
+        {message: 'There must be a space before type annotation colon.'}
+      ],
+      options: ['always'],
+      output: 'type X = { [a :b] :c }'
+    },
+    {
+      code: 'type X = { [a : b] : c }',
+      errors: [
+        {message: 'There must be no space before type annotation colon.'},
+        {message: 'There must be no space before type annotation colon.'}
+      ],
+      options: ['never'],
+      output: 'type X = { [a: b]: c }'
+    },
+    {
+      code: 'type X = { [a  : b]  : c }',
+      errors: [
+        {message: 'There must be 1 space before type annotation colon.'},
+        {message: 'There must be 1 space before type annotation colon.'}
+      ],
+      options: ['always'],
+      output: 'type X = { [a : b] : c }'
+    },
+    {
+      code: 'type X = { [a:(b)]:(c) }',
+      errors: [
+        {message: 'There must be a space before type annotation colon.'},
+        {message: 'There must be a space before type annotation colon.'}
+      ],
+      options: ['always'],
+      output: 'type X = { [a :(b)] :(c) }'
+    },
+    {
+      code: 'type X = { [a : (b)] : (c) }',
+      errors: [
+        {message: 'There must be no space before type annotation colon.'},
+        {message: 'There must be no space before type annotation colon.'}
+      ],
+      options: ['never'],
+      output: 'type X = { [a: (b)]: (c) }'
+    }
+  ],
+  valid: [
+    {
+      code: 'type X = { [a : b] : c }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { [a:b]:c }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { +[a : b] : c }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { +[a:b]:c }',
+      options: ['never']
+    },
+    {
+      code: 'type X = { [a : (b)] : (c) }',
+      options: ['always']
+    },
+    {
+      code: 'type X = { [a:(b)]:(c) }',
+      options: ['never']
+    }
+  ]
+};
+
+const TYPE_CAST_EXPRESSIONS = {
+  invalid: [
+    {
+      code: 'const x = ({} :{})',
+      errors: [{message: 'There must be no space before type cast colon.'}],
+      options: ['never'],
+      output: 'const x = ({}:{})'
+    },
+    {
+      code: 'const x = ({}:{})',
+      errors: [{message: 'There must be a space before type cast colon.'}],
+      options: ['always'],
+      output: 'const x = ({} :{})'
+    },
+    {
+      code: 'const x = ({}  :{})',
+      errors: [{message: 'There must be 1 space before type cast colon.'}],
+      options: ['always'],
+      output: 'const x = ({} :{})'
+    },
+    {
+      code: '((x) : string)',
+      errors: [{message: 'There must be no space before type cast colon.'}],
+      options: ['never'],
+      output: '((x): string)'
+    },
+    {
+      code: '((x): string)',
+      errors: [{message: 'There must be a space before type cast colon.'}],
+      options: ['always'],
+      output: '((x) : string)'
+    },
+    {
+      code: '((x)  : string)',
+      errors: [{message: 'There must be 1 space before type cast colon.'}],
+      options: ['always'],
+      output: '((x) : string)'
+    }
+  ],
+  valid: [
+    {
+      code: 'const x = ({}:{})',
+      options: ['never']
+    },
+    {
+      code: 'const x = ({} :{})',
+      options: ['always']
+    },
+    {
+      code: '((x): string)',
+      options: ['never']
+    },
+    {
+      code: '((x) : string)',
+      options: ['always']
+    }
+  ]
+};
+
+const ALL = [
+  ARROW_FUNCTION_PARAMS,
+  ARROW_FUNCTION_RETURN,
+  FUNCTION_PARAMS,
+  FUNCTION_RETURN,
+  FUNCTION_TYPE_PARAMS,
+  CLASS_PROPERTIES,
+  OBJECT_TYPE_PROPERTIES,
+  OBJECT_TYPE_INDEXERS,
+  TYPE_CAST_EXPRESSIONS
+];
+
+export default {
+  invalid: _.flatMap(ALL, (rules) => { return rules.invalid; }),
+  valid: _.flatMap(ALL, (rules) => { return rules.valid; })
+};
diff --git a/tests/rules/assertions/typeIdMatch.js b/tests/rules/assertions/typeIdMatch.js
new file mode 100644
index 0000000..f5cc21c
--- /dev/null
+++ b/tests/rules/assertions/typeIdMatch.js
@@ -0,0 +1,34 @@
+export default {
+  invalid: [
+    {
+      code: 'type foo = {};',
+      errors: [
+        {
+          message: 'Type identifier \'foo\' does not match pattern \'/^([A-Z][a-z0-9]*)+Type$/\'.'
+        }
+      ]
+    },
+    {
+      code: 'type FooType = {};',
+      errors: [
+        {
+          message: 'Type identifier \'FooType\' does not match pattern \'/^foo$/\'.'
+        }
+      ],
+      options: [
+        '^foo$'
+      ]
+    }
+  ],
+  valid: [
+    {
+      code: 'type FooType = {};'
+    },
+    {
+      code: 'type foo = {};',
+      options: [
+        '^foo$'
+      ]
+    }
+  ]
+};
diff --git a/tests/rules/assertions/unionIntersectionSpacing.js b/tests/rules/assertions/unionIntersectionSpacing.js
new file mode 100644
index 0000000..b46274b
--- /dev/null
+++ b/tests/rules/assertions/unionIntersectionSpacing.js
@@ -0,0 +1,202 @@
+const UNION = {
+  invalid: [
+    {
+      code: 'type X = string| number;',
+      errors: [{message: 'There must be a space before union type annotation separator'}],
+      output: 'type X = string | number;'
+    },
+    {
+      code: 'type X = string| number;',
+      errors: [{message: 'There must be a space before union type annotation separator'}],
+      options: ['always'],
+      output: 'type X = string | number;'
+    },
+    {
+      code: 'type X = string |number;',
+      errors: [{message: 'There must be a space after union type annotation separator'}],
+      output: 'type X = string | number;'
+    },
+    {
+      code: 'type X = string|number;',
+      errors: [
+                {message: 'There must be a space before union type annotation separator'},
+                {message: 'There must be a space after union type annotation separator'}
+      ],
+      output: 'type X = string | number;'
+    },
+    {
+      code: 'type X = {x: string}|{y: number};',
+      errors: [
+                {message: 'There must be a space before union type annotation separator'},
+                {message: 'There must be a space after union type annotation separator'}
+      ],
+      output: 'type X = {x: string} | {y: number};'
+    },
+    {
+      code: 'type X = string | number |boolean;',
+      errors: [{message: 'There must be a space after union type annotation separator'}],
+      output: 'type X = string | number | boolean;'
+    },
+    {
+      code: 'type X = string|number|boolean;',
+      errors: [
+                {message: 'There must be a space before union type annotation separator'},
+                {message: 'There must be a space after union type annotation separator'},
+                {message: 'There must be a space before union type annotation separator'},
+                {message: 'There must be a space after union type annotation separator'}
+      ],
+      output: 'type X = string | number | boolean;'
+    },
+    {
+      code: 'type X = (string)| number;',
+      errors: [{message: 'There must be a space before union type annotation separator'}],
+      output: 'type X = (string) | number;'
+    },
+    {
+      code: 'type X = ((string))|(number | foo);',
+      errors: [
+                {message: 'There must be a space before union type annotation separator'},
+                {message: 'There must be a space after union type annotation separator'}
+      ],
+      output: 'type X = ((string)) | (number | foo);'
+    },
+    {
+      code: 'type X = string |number;',
+      errors: [{message: 'There must be no space before union type annotation separator'}],
+      options: ['never'],
+      output: 'type X = string|number;'
+    },
+    {
+      code: 'type X = string| number;',
+      errors: [{message: 'There must be no space after union type annotation separator'}],
+      options: ['never'],
+      output: 'type X = string|number;'
+    }
+  ],
+  valid: [
+        {code: 'type X = string | number;'},
+        {code: 'type X = string | number | boolean;'},
+        {code: 'type X = (string) | number;'},
+        {code: 'type X = ((string)) | (number | foo);'},
+    {
+      code: 'type X = string|number',
+      options: ['never']
+    },
+    {
+      code: 'type X =\n| string\n| number'
+    },
+    {
+      code: [
+        'function x() {',
+        'type X =',
+        '| string',
+        '| number',
+        '}'
+      ].join('\n')
+    }
+  ]
+};
+
+const INTERSECTION = {
+  invalid: [
+    {
+      code: 'type X = string& number;',
+      errors: [{message: 'There must be a space before intersection type annotation separator'}],
+      output: 'type X = string & number;'
+    },
+    {
+      code: 'type X = string& number;',
+      errors: [{message: 'There must be a space before intersection type annotation separator'}],
+      options: ['always'],
+      output: 'type X = string & number;'
+    },
+    {
+      code: 'type X = string &number;',
+      errors: [{message: 'There must be a space after intersection type annotation separator'}],
+      output: 'type X = string & number;'
+    },
+    {
+      code: 'type X = {x: string}&{y: number};',
+      errors: [
+                {message: 'There must be a space before intersection type annotation separator'},
+                {message: 'There must be a space after intersection type annotation separator'}
+      ],
+      output: 'type X = {x: string} & {y: number};'
+    },
+    {
+      code: 'type X = string&number;',
+      errors: [
+                {message: 'There must be a space before intersection type annotation separator'},
+                {message: 'There must be a space after intersection type annotation separator'}
+      ],
+      output: 'type X = string & number;'
+    },
+    {
+      code: 'type X = string & number &boolean;',
+      errors: [{message: 'There must be a space after intersection type annotation separator'}],
+      output: 'type X = string & number & boolean;'
+    },
+    {
+      code: 'type X = string&number&boolean;',
+      errors: [
+                {message: 'There must be a space before intersection type annotation separator'},
+                {message: 'There must be a space after intersection type annotation separator'},
+                {message: 'There must be a space before intersection type annotation separator'},
+                {message: 'There must be a space after intersection type annotation separator'}
+      ],
+      output: 'type X = string & number & boolean;'
+    },
+    {
+      code: 'type X = (string)& number;',
+      errors: [{message: 'There must be a space before intersection type annotation separator'}],
+      output: 'type X = (string) & number;'
+    },
+    {
+      code: 'type X = ((string))&(number & foo);',
+      errors: [
+                {message: 'There must be a space before intersection type annotation separator'},
+                {message: 'There must be a space after intersection type annotation separator'}
+      ],
+      output: 'type X = ((string)) & (number & foo);'
+    },
+    {
+      code: 'type X = string &number;',
+      errors: [{message: 'There must be no space before intersection type annotation separator'}],
+      options: ['never'],
+      output: 'type X = string&number;'
+    },
+    {
+      code: 'type X = string& number;',
+      errors: [{message: 'There must be no space after intersection type annotation separator'}],
+      options: ['never'],
+      output: 'type X = string&number;'
+    }
+  ],
+  valid: [
+        {code: 'type X = string & number;'},
+        {code: 'type X = string & number & boolean;'},
+        {code: 'type X = (string) & number;'},
+        {code: 'type X = ((string)) & (number & foo);'},
+    {
+      code: 'type X = string&number',
+      options: ['never']
+    },
+    {
+      code: 'type X =\n& string\n& number'
+    },
+    {
+      code: [
+        'function x() {',
+        'type X =',
+        '& string',
+        '& number',
+        '}'
+      ].join('\n')
+    }
+  ]
+};
+
+export default {
+  invalid: [...UNION.invalid, ...INTERSECTION.invalid],
+  valid: [...UNION.valid, ...INTERSECTION.valid]
+};
diff --git a/tests/rules/assertions/useFlowType.js b/tests/rules/assertions/useFlowType.js
new file mode 100644
index 0000000..cccdaba
--- /dev/null
+++ b/tests/rules/assertions/useFlowType.js
@@ -0,0 +1,190 @@
+import {
+    RuleTester
+} from 'eslint';
+import noUnusedVarsRule from 'eslint/lib/rules/no-unused-vars';
+import useFlowType from './../../../src/rules/useFlowType';
+
+const VALID_WITH_USE_FLOW_TYPE = [
+  {
+    code: 'declare class A {}',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: 'declare function A(): Y',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: 'declare module A {}',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: 'declare module A { declare var a: Y }',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: 'declare var A: Y',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: 'import type A from "a"; (function<T: A>(): T {})',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: '(function<T: A>(): T {}); import type A from "a"',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: 'import type {A} from "a"; (function<T: A>(): T {})',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: '(function<T: A>(): T {}); import type {A} from "a"',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: '(function<T: A>(): T {}); import type {a as A} from "a"',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: 'type A = {}; function x<Y: A>(i: Y) { i }; x()',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: 'function x<Y: A>(i: Y) { i }; type A = {}; x()',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: 'type A = {}; function x<Y: A.B.C>(i: Y) { i }; x()',
+        // QualifiedTypeIdentifier -------^
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: 'function x<Y: A.B.C>(i: Y) { i }; type A = {}; x()',
+        //                   ^- QualifiedTypeIdentifier
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  }
+];
+
+const ALWAYS_INVALID = [
+  {
+    code: 'type A = Y',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: 'function x<A>() {}; x()',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  },
+  {
+    code: 'import type A from "a";',
+    errors: [
+      '\'A\' is defined but never used.'
+    ]
+  }
+];
+
+const ALWAYS_VALID = [
+  'type A = Y; var x: A; x()',
+  'var x: A; type A = Y; x()',
+  'type A = Y; function x(a: A) { a() }; x()',
+  'function x(a: A) { a() }; type A = Y; x()',
+  'type A = Y; (x: A)',
+  '(x: A); type A = Y',
+  'function x<A>(): A {}; x()',
+  'import type A from "a"; (function(): A {})',
+  '(function(): A {}); import type A from "a";',
+  'declare interface A {}',
+  'declare type A = {}'
+];
+
+/**
+ * This rule is tested differently than the rest because `RuleTester` is
+ * designed to test rule reporting and use-flow-type doesn't report
+ * anything. use-flow-type suppresses reports from no-unused-vars. So we're
+ * actually testing no-unused-vars's reporting with use-flow-type enabled.
+ */
+{
+  const ruleTester = new RuleTester({
+    parser: 'babel-eslint'
+  });
+
+  ruleTester.run('no-unused-vars must not trigger an error in these cases', noUnusedVarsRule, {
+    invalid: [],
+    valid: ALWAYS_VALID
+  });
+}
+
+{
+  const ruleTester = new RuleTester({
+    parser: 'babel-eslint'
+  });
+
+  ruleTester.run('no-unused-vars must trigger an error in these cases', noUnusedVarsRule, {
+    invalid: [
+      ...ALWAYS_INVALID,
+      ...VALID_WITH_USE_FLOW_TYPE
+    ],
+    valid: []
+  });
+}
+
+{
+  const ruleTester = new RuleTester({
+    parser: 'babel-eslint',
+    rules: {
+      'use-flow-type': 1
+    }
+  });
+
+  ruleTester.defineRule('use-flow-type', useFlowType);
+  ruleTester.run('use-flow-type must not affect no-unused-vars behavior in these cases', noUnusedVarsRule, {
+    invalid: ALWAYS_INVALID,
+    valid: ALWAYS_VALID
+  });
+}
+
+export default {
+  invalid: [],
+  valid: [
+    ...VALID_WITH_USE_FLOW_TYPE.map((subject) => {
+      return {
+        code: subject.code,
+        rules: {
+          'no-unused-vars': 1
+        }
+      };
+    })
+  ]
+};
+
diff --git a/tests/rules/assertions/validSyntax.js b/tests/rules/assertions/validSyntax.js
new file mode 100644
index 0000000..3bffe34
--- /dev/null
+++ b/tests/rules/assertions/validSyntax.js
@@ -0,0 +1,13 @@
+export default {
+  invalid: [
+    // removed, as Babylon now prevents the invalid syntax
+  ],
+  valid: [
+    {
+      code: 'function x(foo: string = "1") {}'
+    },
+    {
+      code: 'function x(foo: Type = bar()) {}'
+    }
+  ]
+};
diff --git a/tests/rules/index.js b/tests/rules/index.js
new file mode 100644
index 0000000..011d7af
--- /dev/null
+++ b/tests/rules/index.js
@@ -0,0 +1,51 @@
+import _ from 'lodash';
+import {
+    RuleTester
+} from 'eslint';
+import plugin from './../../src';
+
+const ruleTester = new RuleTester();
+
+const reportingRules = [
+  'boolean-style',
+  'define-flow-type',
+  'delimiter-dangle',
+  'generic-spacing',
+  'no-dupe-keys',
+  'no-weak-types',
+  'object-type-delimiter',
+  'require-parameter-type',
+  'require-return-type',
+  'require-valid-file-annotation',
+  'semi',
+  'sort-keys',
+  'space-after-type-colon',
+  'space-before-type-colon',
+  'space-before-generic-bracket',
+  'union-intersection-spacing',
+  'type-id-match',
+  'use-flow-type',
+  'valid-syntax'
+];
+
+const parser = require.resolve('babel-eslint');
+
+for (const ruleName of reportingRules) {
+    /* eslint-disable global-require */
+  const assertions = require('./assertions/' + _.camelCase(ruleName));
+    /* eslint-enable global-require */
+
+  assertions.invalid = _.map(assertions.invalid, (assertion) => {
+    assertion.parser = parser;
+
+    return assertion;
+  });
+
+  assertions.valid = _.map(assertions.valid, (assertion) => {
+    assertion.parser = parser;
+
+    return assertion;
+  });
+
+  ruleTester.run(ruleName, plugin.rules[ruleName], assertions);
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-eslint-plugin-flowtype.git



More information about the Pkg-javascript-commits mailing list