Repository: yannickcr/eslint-plugin-react
Pull request #1374 (2017-08-15 15:20:29)

Rule proposal: no-access-state-in-setstate
This rule prevents the use of `this.state` within `this.setState`. It is further described in `docs/rules/no-access-state-in-setstate.md` in the PR, but to summarize: `this.setState` is async, and referring to `this.state` within it may lead to race conditions. 

This is my first eslint-plugin PR, so I am really happy to get any kind of feedback.

edit: 
This is also the recommended way doing it in the [react docs](https://facebook.github.io/react/docs/react-component.html#setstate): 
> If the next state depends on the previous state, we recommend using the updater function form, instead
> ```
> this.setState((prevState) => {
>  return {counter: prevState.quantity + 1};
>}); 
> ```


Patch:
diff --git a/.eslintrc b/.eslintrc
index 132dcd6c..05912521 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -3,10 +3,10 @@
        "es6": true,
        "node": true
     },
-    "parserOptions": {
-      "ecmaVersion": 6,
-      "ecmaFeatures": {
-          "jsx": true
+    parserOptions: {
+      ecmaVersion: 6,
+      ecmaFeatures: {
+          jsx: true
       }
     },
     "rules": {
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 70b8a0c2..ba7ee49d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,156 +3,6 @@ All notable changes to this project will be documented in this file.
 This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
-## [7.4.0] - 2017-09-24
-### Added
-- Add Flow 0.53 support ([#1376][] @jseminck)
-- Add [`jsx-curly-brace-presence`][] rule ([#1310][] @jackyho112)
-- Add support for Flow IntersectionTypeAnnotation to [`prop-types`][] and [`no-unused-prop-types`][] ([#1364][] [#1323][] @jseminck)
-- Add support for Flow TypedArgument to [`no-unused-prop-types`][] ([#1412][] @jseminck)
-- Add support for Flow ClassExpressions to [`prop-types`][] ([#1400][] @jseminck)
-- Add support for Flow read-only props to [`no-unused-prop-types`][] ([#1388][] @jseminck)
-- Add more tests for [`prop-types`][] and [`no-unused-prop-types`][] ([#1381][] @DianaSuvorova)
-- Add support for increment and decrement operations to [`no-direct-mutation-state`][] ([#1386][] @zpao)
-
-### Fixed
-- Fix [`no-unused-state`][] to ignore computed property keys ([#1361][] @jackyho112)
-- Fix [`no-typos`][] crash ([#1406][] @jseminck)
-- Fix [`boolean-prop-naming`][] crash ([#1409][] @EvHaus)
-- Fix [`prop-types`][] and [`no-unused-prop-types`][] crash with IntersectionTypeAnnotation ([#1413][] @jseminck)
-
-### Changed
-- Documentation improvements ([#1392][] @xcatliu, [#1403][] @piperchester, [#1432][] @jneuendorf)
-
-[7.4.0]: https://github.com/yannickcr/eslint-plugin-react/compare/v7.3.0...v7.4.0
-[#1376]: https://github.com/yannickcr/eslint-plugin-react/issues/1376
-[#1310]: https://github.com/yannickcr/eslint-plugin-react/issues/1310
-[#1364]: https://github.com/yannickcr/eslint-plugin-react/issues/1364
-[#1323]: https://github.com/yannickcr/eslint-plugin-react/issues/1323
-[#1412]: https://github.com/yannickcr/eslint-plugin-react/pull/1412
-[#1400]: https://github.com/yannickcr/eslint-plugin-react/pull/1400
-[#1388]: https://github.com/yannickcr/eslint-plugin-react/issues/1388
-[#1381]: https://github.com/yannickcr/eslint-plugin-react/pull/1381
-[#1361]: https://github.com/yannickcr/eslint-plugin-react/issues/1361
-[#1406]: https://github.com/yannickcr/eslint-plugin-react/pull/1406
-[#1409]: https://github.com/yannickcr/eslint-plugin-react/pull/1409
-[#1392]: https://github.com/yannickcr/eslint-plugin-react/pull/1392
-[#1403]: https://github.com/yannickcr/eslint-plugin-react/pull/1403
-[#1386]: https://github.com/yannickcr/eslint-plugin-react/issues/1386
-[#1413]: https://github.com/yannickcr/eslint-plugin-react/issues/1413
-[#1432]: https://github.com/yannickcr/eslint-plugin-react/pull/1432
-
-## [7.3.0] - 2017-08-21
-### Added
-* Add checks for `propTypes`, `contextTypes` and `childContextTypes` to [`no-typos`][] ([#213][] @DianaSuvorova)
-
-### Fixed
-* Fix [`boolean-prop-naming`][] crash ([#1369][] @EvHaus)
-* Fix [`no-typos`][] crash ([#1353][] @jseminck)
-* Fix [`require-default-props`][] stopping when it finds a component without props ([#1380][] @brgibson)
-* Fix [`no-direct-mutation-state`][] detection with nested components ([#1382][])
-
-### Changed
-* Documentation improvements ([#1383][] @mjomble)
-
-[7.3.0]: https://github.com/yannickcr/eslint-plugin-react/compare/v7.2.1...v7.3.0
-[#213]: https://github.com/yannickcr/eslint-plugin-react/issues/213
-[#1369]: https://github.com/yannickcr/eslint-plugin-react/issues/1369
-[#1353]: https://github.com/yannickcr/eslint-plugin-react/issues/1353
-[#1380]: https://github.com/yannickcr/eslint-plugin-react/pull/1380
-[#1382]: https://github.com/yannickcr/eslint-plugin-react/issues/1382
-[#1383]: https://github.com/yannickcr/eslint-plugin-react/pull/1383
-
-## [7.2.1] - 2017-08-14
-### Fixed
-* Fix [`forbid-prop-types`][] crash on identifiers ([#1352][] @ljharb)
-* Fix [`boolean-prop-naming`][] crash with propTypes wrapper ([#1354][] @dustinsoftware)
-* Fix [`prop-types`][] false positive with local variable `props` ([#1288][] @DianaSuvorova)
-* Fix wrapped propTypes detection ([#1366][])
-
-### Changed
-* Documentation improvements ([#1123][] @penx)
-
-[7.2.1]: https://github.com/yannickcr/eslint-plugin-react/compare/v7.2.0...v7.2.1
-[#1352]: https://github.com/yannickcr/eslint-plugin-react/issues/1352
-[#1354]: https://github.com/yannickcr/eslint-plugin-react/issues/1354
-[#1288]: https://github.com/yannickcr/eslint-plugin-react/issues/1288
-[#1366]: https://github.com/yannickcr/eslint-plugin-react/issues/1366
-[#1123]: https://github.com/yannickcr/eslint-plugin-react/issues/1123
-
-## [7.2.0] - 2017-08-09
-### Added
-* Add [`no-unused-state`][] rule ([#1103][] @wbinnssmith)
-* Add [`boolean-prop-naming`][] rule ([#1264][] @EvHaus)
-* Add [`no-typos`][] rule ([#1189][] @jseminck, [#1294][] @haridusenadeera)
-* Add auto fix for [`jsx-sort-props`][] ([#1273][] @Overload119)
-* Add `getters` and `setters` groups to [`sort-comp`][] ([#100][] @RDGthree)
-* Add `noStrings` option to [`jsx-no-literals`][] ([#1202][] @deecewan)
-* Add inverse option for `always`/`never` to [`jsx-boolean-value`][] ([#1249][] @ljharb)
-
-### Fixed
-* Fix [`no-direct-mutation-state`][] to disallow `this.state` mutation in constructor ([#832][] @burabure)
-* Fix [`jsx-no-target-blank`][] crash on empty `rel` attribute ([#1269][] @dustinsoftware)
-* Fix [`sort-comp`][] component detection with `ClassExpression` ([#1076][] @webOS101)
-* Fix [`no-unused-prop-types`][] detection with async class properties and methods ([#1053][] @benstepp)
-* Fix [`void-dom-elements-no-children`][] crash ([#1226][] @kokobeware)
-* Fix [`no-danger-with-children`][] to ignore line breaks ([#1262][])
-* Fix [`no-danger-with-children`][] crash with undefined ([#1287][])
-* Fix [`jsx-no-target-blank`][] crash ([#1296][] @jseminck)
-* Fix [`no-unused-prop-types`][] to no longer ignore components with no used props ([#1303][] @DianaSuvorova)
-* Fix [`jsx-no-duplicate-props`][] crash ([#969][] @marcelmokos)
-* Fix [`jsx-no-literals`][] false positives ([#1301][] @davidyorr)
-* Fix [`no-find-dom-node`][] detection with named imports ([#785][] @Hypnosphi)
-* Fix proTypes-related rules detection with wrapped propTypes ([#1266][] @dustinsoftware)
-* Fix [`no-unused-prop-types`][] detection with propTypes wrapped in a function ([#1253][] @dustinsoftware)
-* Fix [`no-unused-prop-types`][] detection with destructured use of properties ([#816][] @DianaSuvorova)
-* Fix [`no-unused-prop-types`][] detection with inline functions ([#1309][] @DianaSuvorova)
-* Fix [`no-unused-prop-types`][] `skipShapeProps` option with Flow annotations ([#1335][] @DianaSuvorova)
-* Fix [`jsx-curly-spacing`][] schema incompatibility with ESLint 4.2.0 ([#1290][] @jseminck)
-
-### Changed
-* Documentation improvements ([#1261][] @mminer, [#1005][] @yooungt13, [#1289][] @konekoya, [#1308][] @xcatliu, [#1306][] @egberts, [#1329][] [#1344][] @DianaSuvorova)
-* ES6-ify codebase ([#1274][] [#1277][] [#1281][] @dfilipidisz)
-* Code refactoring (@ljharb)
-* Update Travis CI and AppVeyor CI configurations (@lencioni)
-
-[7.2.0]: https://github.com/yannickcr/eslint-plugin-react/compare/v7.1.0...v7.2.0
-[#1103]: https://github.com/yannickcr/eslint-plugin-react/pull/1103
-[#1273]: https://github.com/yannickcr/eslint-plugin-react/pull/1273
-[#1264]: https://github.com/yannickcr/eslint-plugin-react/pull/1264
-[#1189]: https://github.com/yannickcr/eslint-plugin-react/issues/1189
-[#1294]: https://github.com/yannickcr/eslint-plugin-react/pull/1294
-[#100]: https://github.com/yannickcr/eslint-plugin-react/issues/100
-[#1202]: https://github.com/yannickcr/eslint-plugin-react/pull/1202
-[#1249]: https://github.com/yannickcr/eslint-plugin-react/issues/1249
-[#832]: https://github.com/yannickcr/eslint-plugin-react/issues/832
-[#1269]: https://github.com/yannickcr/eslint-plugin-react/issues/1269
-[#1076]: https://github.com/yannickcr/eslint-plugin-react/issues/1076
-[#1053]: https://github.com/yannickcr/eslint-plugin-react/issues/1053
-[#1226]: https://github.com/yannickcr/eslint-plugin-react/pull/1226
-[#1262]: https://github.com/yannickcr/eslint-plugin-react/issues/1262
-[#1287]: https://github.com/yannickcr/eslint-plugin-react/issues/1287
-[#1296]: https://github.com/yannickcr/eslint-plugin-react/issues/1296
-[#1303]: https://github.com/yannickcr/eslint-plugin-react/pull/1303
-[#969]: https://github.com/yannickcr/eslint-plugin-react/issues/969
-[#1301]: https://github.com/yannickcr/eslint-plugin-react/issues/1301
-[#785]: https://github.com/yannickcr/eslint-plugin-react/issues/785
-[#1266]: https://github.com/yannickcr/eslint-plugin-react/issues/1266
-[#1253]: https://github.com/yannickcr/eslint-plugin-react/pull/1253
-[#816]: https://github.com/yannickcr/eslint-plugin-react/issues/816
-[#1309]: https://github.com/yannickcr/eslint-plugin-react/issues/1309
-[#1261]: https://github.com/yannickcr/eslint-plugin-react/pull/1261
-[#1005]: https://github.com/yannickcr/eslint-plugin-react/pull/1005
-[#1289]: https://github.com/yannickcr/eslint-plugin-react/pull/1289
-[#1308]: https://github.com/yannickcr/eslint-plugin-react/pull/1308
-[#1306]: https://github.com/yannickcr/eslint-plugin-react/issues/1306
-[#1329]: https://github.com/yannickcr/eslint-plugin-react/pull/1329
-[#1274]: https://github.com/yannickcr/eslint-plugin-react/pull/1274
-[#1277]: https://github.com/yannickcr/eslint-plugin-react/pull/1277
-[#1281]: https://github.com/yannickcr/eslint-plugin-react/pull/1281
-[#1335]: https://github.com/yannickcr/eslint-plugin-react/issues/1335
-[#1344]: https://github.com/yannickcr/eslint-plugin-react/pull/1344
-[#1290]: https://github.com/yannickcr/eslint-plugin-react/pull/1290
-
 ## [7.1.0] - 2017-06-13
 ### Added
 * Add [`default-props-match-prop-types`][] rule ([#1022][] @webOS101)
@@ -679,7 +529,7 @@ React ([#1073][] @jomasti)
 * Add Node.js 0.10 as minimum required version ([#657][] @jokeyrhyme)
 
 ### Fixed
-* Fix [`jsx-handler-names`][] incorrectly flagging `only` ([#571][] @lencioni)
+* Fix [`jsx-handler-names`][] incorrectly flagging [`only`][] ([#571][] @lencioni)
 * Fix spread props cash in [`jsx-no-target-blank`][] ([#679][] @randycoulman)
 * Fix [`require-optimization`][] warning on stateless components ([#687][])
 * Fix [`jsx-uses-vars`][] that incorrectly marked some variables as used ([#694][] @lencioni)
@@ -1505,7 +1355,7 @@ If you're still not using React 15 you can keep the old behavior by setting the
 * In [`jsx-curly-spacing`][] braces spanning multiple lines are now allowed with `never` option ([#156][] @mathieumg)
 
 ### Fixed
-* Fix multiple var and destructuring handling in [`prop-types`][] ([#159][])
+* Fix multiple var and destructuring handling in [`props-types`][] ([#159][])
 * Fix crash when retrieving propType name ([#163][])
 
 [3.0.0]: https://github.com/yannickcr/eslint-plugin-react/compare/v2.7.1...v3.0.0
@@ -1950,11 +1800,8 @@ If you're still not using React 15 you can keep the old behavior by setting the
 [`default-props-match-prop-types`]: docs/rules/default-props-match-prop-types.md
 [`no-redundant-should-component-update`]: docs/rules/no-redundant-should-component-update.md
 [`jsx-closing-tag-location`]: docs/rules/jsx-closing-tag-location.md
-[`no-unused-state`]: docs/rules/no-unused-state.md
-[`boolean-prop-naming`]: docs/rules/boolean-prop-naming.md
-[`no-typos`]: docs/rules/no-typos.md
+
 [`jsx-sort-prop-types`]: docs/rules/sort-prop-types.md
 [`require-extension`]: docs/rules/require-extension.md
 [`no-comment-textnodes`]: docs/rules/jsx-no-comment-textnodes.md
 [`wrap-multilines`]: docs/rules/jsx-wrap-multilines.md
-[`jsx-curly-brace-presence`]: docs/rules/jsx-curly-brace-presence.md
diff --git a/README.md b/README.md
index 35312840..92be7dbf 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,6 @@ You can also specify some settings that will be shared across all the plugin rul
       "createClass": "createReactClass", // Regex for Component Factory to use, default to "createReactClass"
       "pragma": "React",  // Pragma to use, default to "React"
       "version": "15.0" // React version, default to the latest React stable release
-      "flowVersion": "0.53" // Flow version
     },
     "propWrapperFunctions": [ "forbidExtraProps" ] // The names of any functions used to wrap the propTypes object, such as `forbidExtraProps`. If this isn't set, any propTypes wrapped in a function will be skipped.
   }
@@ -89,6 +88,7 @@ Finally, enable all of the rules that you would like to use.  Use [our preset](#
 * [react/forbid-elements](docs/rules/forbid-elements.md): Forbid certain elements
 * [react/forbid-prop-types](docs/rules/forbid-prop-types.md): Forbid certain propTypes
 * [react/forbid-foreign-prop-types](docs/rules/forbid-foreign-prop-types.md): Forbid foreign propTypes
+* [react/no-access-state-in-setstate](docs/rules/no-access-state-in-setstate.md): Prevent using this.state inside this.setState
 * [react/no-array-index-key](docs/rules/no-array-index-key.md): Prevent using Array index in `key` props
 * [react/no-children-prop](docs/rules/no-children-prop.md): Prevent passing children as props
 * [react/no-danger](docs/rules/no-danger.md): Prevent usage of dangerous JSX properties
@@ -117,7 +117,7 @@ Finally, enable all of the rules that you would like to use.  Use [our preset](#
 * [react/require-optimization](docs/rules/require-optimization.md): Enforce React components to have a `shouldComponentUpdate` method
 * [react/require-render-return](docs/rules/require-render-return.md): Enforce ES5 or ES6 class for returning value in render function
 * [react/self-closing-comp](docs/rules/self-closing-comp.md): Prevent extra closing tags for components without children (fixable)
-* [react/sort-comp](docs/rules/sort-comp.md): Enforce component methods order (fixable)
+* [react/sort-comp](docs/rules/sort-comp.md): Enforce component methods order
 * [react/sort-prop-types](docs/rules/sort-prop-types.md): Enforce propTypes declarations alphabetical sorting
 * [react/style-prop-object](docs/rules/style-prop-object.md): Enforce style prop value being an object
 * [react/void-dom-elements-no-children](docs/rules/void-dom-elements-no-children.md): Prevent void DOM elements (e.g. `<img />`, `<br />`) from receiving children
@@ -142,7 +142,6 @@ Finally, enable all of the rules that you would like to use.  Use [our preset](#
 * [react/jsx-no-literals](docs/rules/jsx-no-literals.md): Prevent usage of unwrapped JSX strings
 * [react/jsx-no-target-blank](docs/rules/jsx-no-target-blank.md): Prevent usage of unsafe `target='_blank'`
 * [react/jsx-no-undef](docs/rules/jsx-no-undef.md): Disallow undeclared variables in JSX
-* [react/jsx-curly-brace-presence](docs/rules/jsx-curly-brace-presence.md): Enforce curly braces or disallow unnecessary curly braces in JSX
 * [react/jsx-pascal-case](docs/rules/jsx-pascal-case.md): Enforce PascalCase for user-defined JSX components
 * [react/jsx-sort-props](docs/rules/jsx-sort-props.md): Enforce props alphabetical sorting (fixable)
 * [react/jsx-space-before-closing](docs/rules/jsx-space-before-closing.md): Validate spacing before closing bracket in JSX (fixable)
diff --git a/docs/rules/jsx-curly-brace-presence.md b/docs/rules/jsx-curly-brace-presence.md
deleted file mode 100644
index b4e27a2b..00000000
--- a/docs/rules/jsx-curly-brace-presence.md
+++ /dev/null
@@ -1,150 +0,0 @@
-# Enforce curly braces or disallow unnecessary curly braces in JSX props and/or children. (react/jsx-curly-brace-presence)
-
-This rule allows you to enforce curly braces or disallow unnecessary curly braces in JSX props and/or children.
-
-For situations where JSX expressions are unnecessary, please refer to [the React doc](https://facebook.github.io/react/docs/jsx-in-depth.html) and [this page about JSX gotchas](https://github.com/facebook/react/blob/v15.4.0-rc.3/docs/docs/02.3-jsx-gotchas.md#html-entities).
-
-**Fixable:** This rule is automatically fixable using the `--fix` flag on the command line
-
-## Rule Details
-
-By default, this rule will check for and warn about unnecessary curly braces in both JSX props and children.
-
-You can pass in options to enforce the presence of curly braces on JSX props or children or both. The same options are available for not allowing unnecessary curly braces as well as ignoring the check.
-
-## Rule Options
-
-```js
-...
-"react/jsx-curly-brace-presence": [<enabled>, { "props": <string>, "children": <string> }]
-...
-```
-
-or alternatively
-
-```js
-...
-"react/jsx-curly-brace-presence": [<enabled>, <string>]
-...
-```
-
-### Valid options for <string>
-
-They are `always`, `never` and `ignore` for checking on JSX props and children.
-
-* `always`: always enforce curly braces inside JSX props or/and children
-* `never`: never allow unnecessary curly braces inside JSX props or/and children
-* `ignore`: ignore the rule for JSX props or/and children
-
-If passed in the option to fix, this is how a style violation will get fixed
-
-* `always`: wrap a JSX attribute in curly braces/JSX expression and/or a JSX child the same way but also with double quotes
-* `never`: get rid of curly braces from a JSX attribute and/or a JSX child
-
-- All fixing operations use double quotes.
-
-For examples:
-
-When `{ props: "always", children: "always" }` is set, the following patterns will be given warnings.
-
-```jsx
-<App>Hello world</App>;
-<App prop='Hello world'>{'Hello world'}</App>;
-```
-
-They can be fixed to:
-
-```jsx
-<App>{"Hello world"}</App>;
-<App prop={"Hello world"}>{'Hello world'}</App>;
-```
-
-When `{ props: "never", children: "never" }` is set, the following patterns will be given warnings.
-
-```jsx
-<App>{'Hello world'}</App>;
-<App prop={'Hello world'} attr={"foo"} />;
-```
-
-They can be fixed to:
-
-```jsx
-<App>Hello world</App>;
-<App prop="Hello world" attr="foo" />;
-```
-
-### Alternative syntax
-
-The options are also `always`, `never` and `ignore` for the same meanings.
-
-In this syntax, only a string is provided and the default will be set to that option for checking on both JSX props and children.
-
-For examples:
-
-When `'always'` is set, the following patterns will be given warnings.
-
-```jsx
-<App>Hello world</App>;
-<App prop='Hello world' attr="foo">Hello world</App>;
-```
-
-They can be fixed to:
-```jsx
-<App>{"Hello world"}</App>;
-<App prop={"Hello world"} attr={"foo"}>{"Hello world"}</App>;
-```
-
-When `'never'` is set, the following pattern will be given warnings.
-
-```jsx
-<App prop={'foo'} attr={"bar"}>{'Hello world'}</App>;
-```
-
-It can fixed to:
-
-```jsx
-<App prop="foo" attr="bar">Hello world</App>;
-```
-
-## Edge cases
-
-The fix also deals with template literals, strings with quotes, and strings with escapes characters.
-
-* If the rule is set to get rid of unnecessary curly braces and the template literal inside a JSX expression has no expression, it will throw a warning and be fixed with double quotes. For example:
-
-```jsx
-<App prop={`Hello world`}>{`Hello world`}</App>;
-```
-
-will be warned and fixed to:
-
-```jsx
-<App prop="Hello world">Hello world</App>;
-```
-
-* If the rule is set to enforce curly braces and the strings have quotes, it will be fixed with double quotes for JSX children and the normal way for JSX attributes.
-
-For example:
-
-
-```jsx
-<App prop='Hello "foo" world'>Hello 'foo' "bar" world</App>;
-```
-
-will warned and fixed to:
-
-```jsx
-<App prop={"Hello \"foo\" world"}>{"Hello 'foo' \"bar\" world"}</App>;
-```
-
-* If the rule is set to get rid of unnecessary curly braces and the strings have escaped characters, it will not warn or fix for JSX children because JSX expressions are necessary in this case. For instance:
-
-The following pattern will not be given a warning even if `'never'` is passed.
-
-```jsx
-<App>{"Hello \u00b7 world"}</App>;
-```
-
-## When Not To Use It
-
-You should turn this rule off if you are not concerned about maintaining consistency regarding the use of curly braces in JSX props and/or children as well as the use of unnecessary JSX expressions.
diff --git a/docs/rules/jsx-sort-props.md b/docs/rules/jsx-sort-props.md
index 5b770514..c0a14019 100644
--- a/docs/rules/jsx-sort-props.md
+++ b/docs/rules/jsx-sort-props.md
@@ -2,8 +2,6 @@
 
 Some developers prefer to sort props names alphabetically to be able to find necessary props easier at the later time. Others feel that it adds complexity and becomes burden to maintain.
 
-**Fixable:** This rule is automatically fixable using the `--fix` flag on the command line.
-
 ## Rule Details
 
 This rule checks all JSX components and verifies that all props are sorted alphabetically. A spread attribute resets the verification. The default configuration of the rule is case-sensitive.
diff --git a/docs/rules/jsx-tag-spacing.md b/docs/rules/jsx-tag-spacing.md
index 75ed07ee..0e168242 100644
--- a/docs/rules/jsx-tag-spacing.md
+++ b/docs/rules/jsx-tag-spacing.md
@@ -2,8 +2,6 @@
 
 Enforce or forbid spaces after the opening bracket, before the closing bracket of self-closing elements, and between the angle bracket and slash of JSX closing or self-closing elements.
 
-**Fixable:** This rule is automatically fixable using the `--fix` flag on the command line.
-
 ## Rule Details
 
 This rule checks the whitespace inside and surrounding the JSX syntactic elements.
diff --git a/docs/rules/no-access-state-in-setstate.md b/docs/rules/no-access-state-in-setstate.md
new file mode 100644
index 00000000..03af0a2b
--- /dev/null
+++ b/docs/rules/no-access-state-in-setstate.md
@@ -0,0 +1,39 @@
+# Prevent using this.state within a this.setState (no-access-state-in-setstate)
+
+This rule should prevent usage of `this.state` inside `setState` calls.
+Such usage of `this.state` might result in errors when two state calls are
+called in batch and thus referencing old state and not the current
+state. An example can be an increment function:
+
+```
+function increment() {
+  this.setState({value: this.state.value + 1});
+}
+```
+
+If these two `setState` operations is grouped together in a batch it will
+look be something like the following, given that value is 1:
+
+```
+setState({value: 1 + 1})
+setState({value: 1 + 1})
+```
+
+This can be avoided with using callbacks which takes the previous state
+as first argument:
+
+```
+function increment() {
+  this.setState(prevState => ({value: prevState.value + 1}));
+}
+```
+
+Then react will call the argument with the correct and updated  state,
+even when things happen in batches. And the example above will be
+something like:
+
+
+```
+setState({value: 1 + 1})
+setState({value: 2 + 1})
+```
diff --git a/docs/rules/no-array-index-key.md b/docs/rules/no-array-index-key.md
index 81e5fe88..7645b51a 100644
--- a/docs/rules/no-array-index-key.md
+++ b/docs/rules/no-array-index-key.md
@@ -95,7 +95,3 @@ things.reduceRight((collection, thing) => (
   collection.concat(<Hello key={thing.id} />)
 ), []);
 ```
-
-## When Not To Use It
-
-If there is nothing unique about the items, for example [you are breaking an array down in to chunks](https://github.com/yannickcr/eslint-plugin-react/issues/1123), then you may want to disable this rule with an override.
diff --git a/docs/rules/no-multi-comp.md b/docs/rules/no-multi-comp.md
index ac972d87..0293fc78 100644
--- a/docs/rules/no-multi-comp.md
+++ b/docs/rules/no-multi-comp.md
@@ -42,7 +42,7 @@ var HelloJohn = createReactClass({
 
 ### `ignoreStateless`
 
-When `true` the rule will ignore stateless components and will allow you to have multiple stateless components, or one stateful component and some stateless components in the same file.
+When `true` the rule will ignore stateless components and will allow you to have multiple stateless components, or one statefull component and some stateless components in the same file.
 
 The following patterns are considered okay and do not cause warnings:
 
@@ -69,4 +69,4 @@ module.exports = HelloJohn;
 
 ## When Not To Use It
 
-If you prefer to declare multiple components per file you can disable this rule.
+If you prefer to declare multiple components per files you can disable this rule.
diff --git a/docs/rules/no-typos.md b/docs/rules/no-typos.md
index ed2bfec8..c61cb704 100644
--- a/docs/rules/no-typos.md
+++ b/docs/rules/no-typos.md
@@ -1,13 +1,13 @@
-# Prevents common typos (react/no-typos)
+# Prevents common casing typos (react/no-typos)
 
 Ensure no casing typos were made declaring static class properties and lifecycle methods.
-Checks that declared `propTypes`, `contextTypes` and `childContextTypes` is supported by [react-props](https://github.com/facebook/prop-types)
 
 ## Rule Details
 
-This rule checks whether the declared static class properties and lifecycle methods related to React components do not contain any typos.
+This rule checks whether the declared static class properties and lifecycle methods related to React components
+do not contain any typos.
 
-It makes sure that the following class properties have
+It currently makes sure that the following class properties have
 no casing typos:
 
 * propTypes
@@ -73,13 +73,6 @@ class MyComponent extends React.Component {
 class MyComponent extends React.Component {
   componentdidupdate() {}
 }
-
-class MyComponent extends React.Component {
-  static propTypes = {
-    a: PropTypes.typo
-  }
-}
-
 ```
 
 The following patterns are not considered warnings:
@@ -112,10 +105,4 @@ class MyComponent extends React.Component {
 class MyComponent extends React.Component {
   componentDidUpdate() {}
 }
-
-class MyComponent extends React.Component {
-  static propTypes = {
-    a: PropTypes.bool.isRequired
-  }
-}
 ```
diff --git a/docs/rules/sort-comp.md b/docs/rules/sort-comp.md
index c1ec19b0..52e8dead 100644
--- a/docs/rules/sort-comp.md
+++ b/docs/rules/sort-comp.md
@@ -1,6 +1,6 @@
 # Enforce component methods order (react/sort-comp)
 
-When creating React components it is more convenient to always follow the same organisation for method order to help you easily find lifecyle methods, event handlers, etc.
+When creating React components it is more convenient to always follow the same organisation for methods order to helps you to easily find lifecyle methods, event handlers, etc.
 
 **Fixable:** This rule is automatically fixable using the [`sort-comp` transform](https://github.com/reactjs/react-codemod/blob/master/transforms/sort-comp.js) in [react-codemod](https://www.npmjs.com/package/react-codemod).
 
diff --git a/index.js b/index.js
index 13b72fdd..bb13066e 100644
--- a/index.js
+++ b/index.js
@@ -28,7 +28,6 @@ const allRules = {
   'jsx-no-literals': require('./lib/rules/jsx-no-literals'),
   'jsx-no-target-blank': require('./lib/rules/jsx-no-target-blank'),
   'jsx-no-undef': require('./lib/rules/jsx-no-undef'),
-  'jsx-curly-brace-presence': require('./lib/rules/jsx-curly-brace-presence'),
   'jsx-pascal-case': require('./lib/rules/jsx-pascal-case'),
   'jsx-sort-props': require('./lib/rules/jsx-sort-props'),
   'jsx-space-before-closing': require('./lib/rules/jsx-space-before-closing'),
@@ -36,6 +35,7 @@ const allRules = {
   'jsx-uses-react': require('./lib/rules/jsx-uses-react'),
   'jsx-uses-vars': require('./lib/rules/jsx-uses-vars'),
   'jsx-wrap-multilines': require('./lib/rules/jsx-wrap-multilines'),
+  'no-access-state-in-setstate': require('./lib/rules/no-access-state-in-setstate'),
   'no-array-index-key': require('./lib/rules/no-array-index-key'),
   'no-children-prop': require('./lib/rules/no-children-prop'),
   'no-danger': require('./lib/rules/no-danger'),
diff --git a/lib/rules/boolean-prop-naming.js b/lib/rules/boolean-prop-naming.js
index c9baaa70..d8c1423f 100644
--- a/lib/rules/boolean-prop-naming.js
+++ b/lib/rules/boolean-prop-naming.js
@@ -1,6 +1,6 @@
 /**
  * @fileoverview Enforces consistent naming for boolean props
- * @author Ev Haus
+ * @author Evgueni Naverniouk
  */
 'use strict';
 
@@ -57,7 +57,7 @@ module.exports = {
     function isPropTypesDeclaration(node) {
       // Special case for class properties
       // (babel-eslint does not expose property name so we have to rely on tokens)
-      if (node && node.type === 'ClassProperty') {
+      if (node.type === 'ClassProperty') {
         const tokens = context.getFirstTokens(node, 2);
         if (tokens[0].value === 'propTypes' || (tokens[1] && tokens[1].value === 'propTypes')) {
           return true;
@@ -118,7 +118,7 @@ module.exports = {
       const component = components.get(node) || node;
       const invalidProps = component.invalidProps || [];
 
-      (proptypes || []).forEach(prop => {
+      proptypes.forEach(prop => {
         const propKey = getPropKey(prop);
         const flowCheck = (
           prop.type === 'ObjectTypeProperty' &&
@@ -180,7 +180,7 @@ module.exports = {
           return;
         }
         const component = utils.getRelatedComponent(node);
-        if (!component || !node.parent.right.properties) {
+        if (!component) {
           return;
         }
         validatePropNaming(component.node, node.parent.right.properties);
diff --git a/lib/rules/default-props-match-prop-types.js b/lib/rules/default-props-match-prop-types.js
index c9a31937..1d020f42 100644
--- a/lib/rules/default-props-match-prop-types.js
+++ b/lib/rules/default-props-match-prop-types.js
@@ -119,7 +119,7 @@ module.exports = {
         propWrapperFunctions.has(node.callee.name) &&
         node.arguments && node.arguments[0]
       ) {
-        return resolveNodeValue(node.arguments[0]);
+        return node.arguments[0];
       }
       return node;
     }
@@ -163,46 +163,23 @@ module.exports = {
       }));
     }
 
-    /**
-     * Handles Props defined in IntersectionTypeAnnotation nodes
-     * e.g. type Props = PropsA & PropsB
-     * @param   {ASTNode} intersectionTypeAnnotation ObjectExpression node.
-     * @returns {Object[]}
-     */
-    function getPropertiesFromIntersectionTypeAnnotationNode(annotation) {
-      return annotation.types.reduce((properties, type) => {
-        annotation = resolveGenericTypeAnnotation(type);
-
-        if (annotation && annotation.id) {
-          annotation = findVariableByName(annotation.id.name);
-        }
-
-        return properties.concat(annotation.properties);
-      }, []);
-    }
-
     /**
      * Extracts a PropType from a TypeAnnotation node.
      * @param   {ASTNode} node TypeAnnotation node.
      * @returns {Object[]}     Array of PropType object representations, to be consumed by `addPropTypesToComponent`.
      */
     function getPropTypesFromTypeAnnotation(node) {
-      let properties = [];
+      let properties;
 
       switch (node.typeAnnotation.type) {
         case 'GenericTypeAnnotation':
           let annotation = resolveGenericTypeAnnotation(node.typeAnnotation);
 
-          if (annotation && annotation.type === 'IntersectionTypeAnnotation') {
-            properties = getPropertiesFromIntersectionTypeAnnotationNode(annotation);
-          } else {
-            if (annotation && annotation.id) {
-              annotation = findVariableByName(annotation.id.name);
-            }
-
-            properties = annotation ? (annotation.properties || []) : [];
+          if (annotation && annotation.id) {
+            annotation = findVariableByName(annotation.id.name);
           }
 
+          properties = annotation ? (annotation.properties || []) : [];
           break;
 
         case 'UnionTypeAnnotation':
@@ -337,6 +314,7 @@ module.exports = {
       if (!component) {
         return;
       }
+
       addPropTypesToComponent(component, getPropTypesFromTypeAnnotation(node.typeAnnotation, context));
     }
 
diff --git a/lib/rules/forbid-prop-types.js b/lib/rules/forbid-prop-types.js
index e01303b6..5e2b37b4 100644
--- a/lib/rules/forbid-prop-types.js
+++ b/lib/rules/forbid-prop-types.js
@@ -3,8 +3,6 @@
  */
 'use strict';
 
-const variableUtil = require('../util/variable');
-
 // ------------------------------------------------------------------------------
 // Constants
 // ------------------------------------------------------------------------------
@@ -69,32 +67,13 @@ module.exports = {
       );
     }
 
-    /**
-     * Find a variable by name in the current scope.
-     * @param  {string} name Name of the variable to look for.
-     * @returns {ASTNode|null} Return null if the variable could not be found, ASTNode otherwise.
-     */
-    function findVariableByName(name) {
-      const variable = variableUtil.variablesInScope(context).find(item => item.name === name);
-
-      if (!variable || !variable.defs[0] || !variable.defs[0].node) {
-        return null;
-      }
-
-      if (variable.defs[0].node.type === 'TypeAlias') {
-        return variable.defs[0].node.right;
-      }
-
-      return variable.defs[0].node.init;
-    }
-
 
     /**
      * Checks if propTypes declarations are forbidden
      * @param {Array} declarations The array of AST nodes being checked.
      * @returns {void}
      */
-    function checkProperties(declarations) {
+    function checkForbidden(declarations) {
       declarations.forEach(declaration => {
         if (declaration.type !== 'Property') {
           return;
@@ -129,34 +108,26 @@ module.exports = {
       });
     }
 
-    function checkNode(node) {
-      switch (node && node.type) {
-        case 'ObjectExpression':
-          checkProperties(node.properties);
-          break;
-        case 'Identifier':
-          const propTypesObject = findVariableByName(node.name);
-          if (propTypesObject && propTypesObject.properties) {
-            checkProperties(propTypesObject.properties);
-          }
-          break;
-        case 'CallExpression':
-          const innerNode = node.arguments && node.arguments[0];
-          if (propWrapperFunctions.has(node.callee.name) && innerNode) {
-            checkNode(innerNode);
-          }
-          break;
-        default:
-          break;
-      }
-    }
-
     return {
       ClassProperty: function(node) {
         if (!isPropTypesDeclaration(node)) {
           return;
         }
-        checkNode(node.value);
+        switch (node.value && node.value.type) {
+          case 'ObjectExpression':
+            checkForbidden(node.value.properties);
+            break;
+          case 'CallExpression':
+            if (
+              propWrapperFunctions.has(node.value.callee.name) &&
+              node.value.arguments && node.value.arguments[0]
+            ) {
+              checkForbidden(node.value.arguments[0].properties);
+            }
+            break;
+          default:
+            break;
+        }
       },
 
       MemberExpression: function(node) {
@@ -164,7 +135,22 @@ module.exports = {
           return;
         }
 
-        checkNode(node.parent.right);
+        const right = node.parent.right;
+        switch (right && right.type) {
+          case 'ObjectExpression':
+            checkForbidden(right.properties);
+            break;
+          case 'CallExpression':
+            if (
+              propWrapperFunctions.has(right.callee.name) &&
+              right.arguments && right.arguments[0]
+            ) {
+              checkForbidden(right.arguments[0].properties);
+            }
+            break;
+          default:
+            break;
+        }
       },
 
       ObjectExpression: function(node) {
@@ -177,7 +163,7 @@ module.exports = {
             return;
           }
           if (property.value.type === 'ObjectExpression') {
-            checkProperties(property.value.properties);
+            checkForbidden(property.value.properties);
           }
         });
       }
diff --git a/lib/rules/jsx-curly-brace-presence.js b/lib/rules/jsx-curly-brace-presence.js
deleted file mode 100644
index 51ef422b..00000000
--- a/lib/rules/jsx-curly-brace-presence.js
+++ /dev/null
@@ -1,189 +0,0 @@
-/**
- * @fileoverview Enforce curly braces or disallow unnecessary curly brace in JSX
- * @author Jacky Ho
- */
-'use strict';
-
-// ------------------------------------------------------------------------------
-// Constants
-// ------------------------------------------------------------------------------
-
-const OPTION_ALWAYS = 'always';
-const OPTION_NEVER = 'never';
-const OPTION_IGNORE = 'ignore';
-
-const OPTION_VALUES = [
-  OPTION_ALWAYS,
-  OPTION_NEVER,
-  OPTION_IGNORE
-];
-const DEFAULT_CONFIG = {props: OPTION_NEVER, children: OPTION_NEVER};
-
-// ------------------------------------------------------------------------------
-// Rule Definition
-// ------------------------------------------------------------------------------
-
-module.exports = {
-  meta: {
-    docs: {
-      description:
-        'Disallow unnecessary JSX expressions when literals alone are sufficient ' +
-          'or enfore JSX expressions on literals in JSX children or attributes',
-      category: 'Stylistic Issues',
-      recommended: false
-    },
-    fixable: 'code',
-
-    schema: [
-      {
-        oneOf: [
-          {
-            type: 'object',
-            properties: {
-              props: {enum: OPTION_VALUES, default: OPTION_NEVER},
-              children: {enum: OPTION_VALUES, default: OPTION_NEVER}
-            },
-            additionalProperties: false
-          },
-          {
-            enum: OPTION_VALUES
-          }
-        ]
-      }
-    ]
-  },
-
-  create: function(context) {
-    const ruleOptions = context.options[0];
-    const userConfig = typeof ruleOptions === 'string' ?
-      {props: ruleOptions, children: ruleOptions} :
-      Object.assign({}, DEFAULT_CONFIG, ruleOptions);
-
-    function containsBackslashForEscaping(rawStringValue) {
-      return rawStringValue.includes('\\');
-    }
-
-    function escapeDoubleQuotes(rawStringValue) {
-      return rawStringValue.replace(/\\"/g, '"').replace(/"/g, '\\"');
-    }
-
-    /**
-     * Report and fix an unnecessary curly brace violation on a node
-     * @param {ASTNode} node - The AST node with an unnecessary JSX expression
-     * @param {String} text - The text to replace the unnecessary JSX expression
-     */
-    function reportUnnecessaryCurly(JSXExpressionNode) {
-      context.report({
-        node: JSXExpressionNode,
-        message: 'Curly braces are unnecessary here.',
-        fix: function(fixer) {
-          const expression = JSXExpressionNode.expression;
-          const expressionType = expression.type;
-          const parentType = JSXExpressionNode.parent.type;
-
-          let textToReplace;
-          if (parentType === 'JSXAttribute') {
-            textToReplace = `"${escapeDoubleQuotes(
-              expressionType === 'TemplateLiteral' ?
-                expression.quasis[0].value.raw :
-                expression.raw.substring(1, expression.raw.length - 1)
-            )}"`;
-          } else {
-            textToReplace = expressionType === 'TemplateLiteral' ?
-              expression.quasis[0].value.cooked : expression.value;
-          }
-
-          return fixer.replaceText(JSXExpressionNode, textToReplace);
-        }
-      });
-    }
-
-    function reportMissingCurly(literalNode) {
-      context.report({
-        node: literalNode,
-        message: 'Need to wrap this literal in a JSX expression.',
-        fix: function(fixer) {
-          const expression = literalNode.parent.type === 'JSXAttribute' ?
-            `{"${escapeDoubleQuotes(
-              literalNode.raw.substring(1, literalNode.raw.length - 1)
-            )}"}` :
-            `{${JSON.stringify(literalNode.value)}}`;
-
-          return fixer.replaceText(literalNode, expression);
-        }
-      });
-    }
-
-    function lintUnnecessaryCurly(JSXExpressionNode) {
-      const expression = JSXExpressionNode.expression;
-      const expressionType = expression.type;
-      const parentType = JSXExpressionNode.parent.type;
-
-      if (
-        expressionType === 'Literal' &&
-          typeof expression.value === 'string' && (
-          parentType === 'JSXAttribute' ||
-          !containsBackslashForEscaping(expression.raw))
-      ) {
-        reportUnnecessaryCurly(JSXExpressionNode);
-      } else if (
-        expressionType === 'TemplateLiteral' &&
-          expression.expressions.length === 0 && (
-          parentType === 'JSXAttribute' ||
-          !containsBackslashForEscaping(expression.quasis[0].value.raw))
-      ) {
-        reportUnnecessaryCurly(JSXExpressionNode);
-      }
-    }
-
-    function areRuleConditionsSatisfied(parentType, config, ruleCondition) {
-      return (
-        parentType === 'JSXAttribute' &&
-          typeof config.props === 'string' &&
-          config.props === ruleCondition
-      ) || (
-        parentType === 'JSXElement' &&
-          typeof config.children === 'string' &&
-          config.children === ruleCondition
-      );
-    }
-
-    function shouldCheckForUnnecessaryCurly(parent, config) {
-      const parentType = parent.type;
-
-      // If there are more than one JSX child, there is no need to check for
-      // unnecessary curly braces.
-      if (parentType === 'JSXElement' && parent.children.length !== 1) {
-        return false;
-      }
-
-      return areRuleConditionsSatisfied(parentType, config, OPTION_NEVER);
-    }
-
-    function shouldCheckForMissingCurly(parentType, config) {
-      return areRuleConditionsSatisfied(parentType, config, OPTION_ALWAYS);
-    }
-
-    // --------------------------------------------------------------------------
-    // Public
-    // --------------------------------------------------------------------------
-
-    return {
-      JSXExpressionContainer: node => {
-        const parent = node.parent;
-
-        if (shouldCheckForUnnecessaryCurly(parent, userConfig)) {
-          lintUnnecessaryCurly(node);
-        }
-      },
-
-      Literal: node => {
-        const parentType = node.parent.type;
-
-        if (shouldCheckForMissingCurly(parentType, userConfig)) {
-          reportMissingCurly(node);
-        }
-      }
-    };
-  }
-};
diff --git a/lib/rules/no-access-state-in-setstate.js b/lib/rules/no-access-state-in-setstate.js
new file mode 100644
index 00000000..f87f393f
--- /dev/null
+++ b/lib/rules/no-access-state-in-setstate.js
@@ -0,0 +1,142 @@
+/**
+ * @fileoverview Prevent usage of this.state within setState
+ * @author Rolf Erik Lekang, Jørgen Aaberg
+ */
+
+'use strict';
+
+// ------------------------------------------------------------------------------
+// Rule Definition
+// ------------------------------------------------------------------------------
+
+module.exports = {
+  meta: {
+    docs: {
+      description: 'Reports when this.state is accessed within setState',
+      category: 'Possible Errors',
+      recommended: false
+    }
+  },
+
+  create: function(context) {
+    function isSetStateCall(node) {
+      return node.type === 'CallExpression' &&
+        node.callee.property &&
+        node.callee.property.name === 'setState' &&
+        node.callee.object.type === 'ThisExpression';
+    }
+
+    // The methods array contains all methods or functions that are using this.state
+    // or that are calling another method or function using this.state
+    const methods = [];
+    // The vars array contains all variables that contains this.state
+    const vars = [];
+    return {
+      CallExpression(node) {
+        // Appends all the methods that are calling another
+        // method containg this.state to the methods array
+        methods.map(method => {
+          if (node.callee.name === method.methodName) {
+            let current = node.parent;
+            while (current.type !== 'Program') {
+              if (current.type === 'MethodDefinition') {
+                methods.push({
+                  methodName: current.key.name,
+                  node: method.node
+                });
+                break;
+              }
+              current = current.parent;
+            }
+          }
+        });
+
+        // Finding all CallExpressions that is inside a setState
+        // to further check if they contains this.state
+        let current = node.parent;
+        while (current.type !== 'Program') {
+          if (isSetStateCall(current)) {
+            const methodName = node.callee.name;
+            methods.map(method => {
+              if (method.methodName === methodName) {
+                context.report(
+                  method.node,
+                  'Use callback in setState when referencing the previous state.'
+                );
+              }
+            });
+
+            break;
+          }
+          current = current.parent;
+        }
+      },
+
+      MemberExpression(node) {
+        if (
+          node.property.name === 'state' &&
+          node.object.type === 'ThisExpression'
+        ) {
+          let current = node;
+          while (current.type !== 'Program') {
+            // Reporting if this.state is directly within this.setState
+            if (isSetStateCall(current)) {
+              context.report(
+                node,
+                'Use callback in setState when referencing the previous state.'
+              );
+              break;
+            }
+
+            // Storing all functions and methods that contains this.state
+            if (current.type === 'MethodDefinition') {
+              methods.push({
+                methodName: current.key.name,
+                node: node
+              });
+              break;
+            } else if (current.type === 'FunctionExpression') {
+              methods.push({
+                methodName: current.parent.key.name,
+                node: node
+              });
+              break;
+            }
+
+            // Storing all variables containg this.state
+            if (current.type === 'VariableDeclarator') {
+              vars.push({
+                node: node,
+                scope: context.getScope()
+              });
+              break;
+            }
+
+            current = current.parent;
+          }
+        }
+      },
+
+      Identifier(node) {
+        // Checks if the identifier is a variable within an object
+        let current = node;
+        while (current.parent.type === 'BinaryExpression') {
+          current = current.parent;
+        }
+        if (current.parent.value === current) {
+          while (current.type !== 'Program') {
+            if (isSetStateCall(current)) {
+              vars
+                .filter(v => v.scope === context.getScope())
+                .map(v => context.report(
+                  v.node,
+                  'Use callback in setState when referencing the previous state.'
+                ));
+            }
+            current = current.parent;
+          }
+        }
+      }
+    };
+  }
+};
diff --git a/lib/rules/no-deprecated.js b/lib/rules/no-deprecated.js
index 0504798c..68804637 100644
--- a/lib/rules/no-deprecated.js
+++ b/lib/rules/no-deprecated.js
@@ -78,7 +78,7 @@ module.exports = {
       return (
         deprecated &&
         deprecated[method] &&
-        versionUtil.testReactVersion(context, deprecated[method][0])
+        versionUtil.test(context, deprecated[method][0])
       );
     }
 
diff --git a/lib/rules/no-direct-mutation-state.js b/lib/rules/no-direct-mutation-state.js
index 40e877a1..120a296b 100644
--- a/lib/rules/no-direct-mutation-state.js
+++ b/lib/rules/no-direct-mutation-state.js
@@ -45,79 +45,39 @@ module.exports = {
       }
     }
 
-    /**
-     * Walks throughs the MemberExpression to the top-most property.
-     * @param {Object} node The node to process
-     * @returns {Object} The outer-most MemberExpression
-     */
-    function getOuterMemberExpression(node) {
-      while (node.object && node.object.property) {
-        node = node.object;
-      }
-      return node;
-    }
-
-    /**
-     * Determine if this MemberExpression is for `this.state`
-     * @param {Object} node The node to process
-     * @returns {Boolean}
-     */
-    function isStateMemberExpression(node) {
-      return node.object.type === 'ThisExpression' && node.property.name === 'state';
-    }
-
-    /**
-     * Determine if we should currently ignore assignments in this component.
-     * @param {?Object} component The component to process
-     * @returns {Boolean} True if we should skip assignment checks.
-     */
-    function shouldIgnoreComponent(component) {
-      return !component || (component.inConstructor && !component.inCallExpression);
-    }
-
     // --------------------------------------------------------------------------
     // Public
     // --------------------------------------------------------------------------
+    let inConstructor = false;
+    let inCallExpression = false;
+
     return {
       MethodDefinition(node) {
         if (node.kind === 'constructor') {
-          components.set(node, {
-            inConstructor: true
-          });
+          inConstructor = true;
         }
       },
 
-      CallExpression: function(node) {
-        components.set(node, {
-          inCallExpression: true
-        });
+      CallExpression: function() {
+        inCallExpression = true;
       },
 
       AssignmentExpression(node) {
-        const component = components.get(utils.getParentComponent());
-        if (shouldIgnoreComponent(component) || !node.left || !node.left.object) {
+        let item;
+        if ((inConstructor && !inCallExpression) || !node.left || !node.left.object) {
           return;
         }
-        const item = getOuterMemberExpression(node.left);
-        if (isStateMemberExpression(item)) {
-          const mutations = (component && component.mutations) || [];
-          mutations.push(node.left.object);
-          components.set(node, {
-            mutateSetState: true,
-            mutations
-          });
+        item = node.left;
+        while (item.object && item.object.property) {
+          item = item.object;
         }
-      },
-
-      UpdateExpression(node) {
-        const component = components.get(utils.getParentComponent());
-        if (shouldIgnoreComponent(component) || node.argument.type !== 'MemberExpression') {
-          return;
-        }
-        const item = getOuterMemberExpression(node.argument);
-        if (isStateMemberExpression(item)) {
+        if (
+          item.object.type === 'ThisExpression' &&
+          item.property.name === 'state'
+        ) {
+          const component = components.get(utils.getParentComponent());
           const mutations = (component && component.mutations) || [];
-          mutations.push(item);
+          mutations.push(node.left.object);
           components.set(node, {
             mutateSetState: true,
             mutations
@@ -125,17 +85,13 @@ module.exports = {
         }
       },
 
-      'CallExpression:exit': function(node) {
-        components.set(node, {
-          inCallExpression: false
-        });
+      'CallExpression:exit': function() {
+        inCallExpression = false;
       },
 
       'MethodDefinition:exit': function (node) {
         if (node.kind === 'constructor') {
-          components.set(node, {
-            inConstructor: false
-          });
+          inConstructor = false;
         }
       },
 
diff --git a/lib/rules/no-render-return-value.js b/lib/rules/no-render-return-value.js
index db387310..e8544813 100644
--- a/lib/rules/no-render-return-value.js
+++ b/lib/rules/no-render-return-value.js
@@ -35,11 +35,11 @@ module.exports = {
         }
 
         let calleeObjectName = /^ReactDOM$/;
-        if (versionUtil.testReactVersion(context, '15.0.0')) {
+        if (versionUtil.test(context, '15.0.0')) {
           calleeObjectName = /^ReactDOM$/;
-        } else if (versionUtil.testReactVersion(context, '0.14.0')) {
+        } else if (versionUtil.test(context, '0.14.0')) {
           calleeObjectName = /^React(DOM)?$/;
-        } else if (versionUtil.testReactVersion(context, '0.13.0')) {
+        } else if (versionUtil.test(context, '0.13.0')) {
           calleeObjectName = /^React$/;
         }
 
diff --git a/lib/rules/no-typos.js b/lib/rules/no-typos.js
index 98a161ea..60426c4e 100644
--- a/lib/rules/no-typos.js
+++ b/lib/rules/no-typos.js
@@ -21,12 +21,10 @@ const LIFECYCLE_METHODS = [
   'render'
 ];
 
-const PROP_TYPES = Object.keys(require('prop-types'));
-
 module.exports = {
   meta: {
     docs: {
-      description: 'Prevent common typos',
+      description: 'Prevent common casing typos',
       category: 'Stylistic Issues',
       recommended: false
     },
@@ -34,56 +32,7 @@ module.exports = {
   },
 
   create: Components.detect((context, components, utils) => {
-    function checkValidPropTypeQualfier(node) {
-      if (node.name !== 'isRequired') {
-        context.report({
-          node: node,
-          message: `Typo in prop type chain qualifier: ${node.name}`
-        });
-      }
-    }
-
-    function checkValidPropType(node) {
-      if (node.name && !PROP_TYPES.some(propTypeName => propTypeName === node.name)) {
-        context.report({
-          node: node,
-          message: `Typo in declared prop type: ${node.name}`
-        });
-      }
-    }
-
-    /* eslint-disable no-use-before-define */
-    function checkValidProp(node) {
-      if (node && node.type === 'MemberExpression' && node.object.type === 'MemberExpression') {
-        checkValidPropType(node.object.property);
-        checkValidPropTypeQualfier(node.property);
-      } else if (node && node.type === 'MemberExpression' && node.object.type === 'Identifier') {
-        checkValidPropType(node.property);
-      } else if (node && node.type === 'CallExpression') {
-        const callee = node.callee;
-        if (callee.type === 'MemberExpression' && callee.property.name === 'shape') {
-          checkValidPropObject(node.arguments[0]);
-        } else if (callee.type === 'MemberExpression' && callee.property.name === 'oneOfType') {
-          const args = node.arguments[0];
-          if (args && args.type === 'ArrayExpression') {
-            args.elements.forEach(el => checkValidProp(el));
-          }
-        }
-      }
-    }
-
-    function checkValidPropObject (node) {
-      if (node.type === 'ObjectExpression') {
-        node.properties.forEach(prop => checkValidProp(prop.value));
-      }
-    }
-    /* eslint-enable no-use-before-define */
-
     function reportErrorIfClassPropertyCasingTypo(node, propertyName) {
-      if (propertyName === 'propTypes' || propertyName === 'contextTypes' || propertyName === 'childContextTypes') {
-        const propsNode = node && node.parent && node.parent.type === 'AssignmentExpression' && node.parent.right;
-        checkValidPropObject(propsNode);
-      }
       STATIC_CLASS_PROPERTIES.forEach(CLASS_PROP => {
         if (propertyName && CLASS_PROP.toLowerCase() === propertyName.toLowerCase() && CLASS_PROP !== propertyName) {
           context.report({
@@ -117,21 +66,13 @@ module.exports = {
       },
 
       MemberExpression: function(node) {
-        const propertyName = node.property.name;
-
-        if (
-          !propertyName ||
-          STATIC_CLASS_PROPERTIES.map(prop => prop.toLocaleLowerCase()).indexOf(propertyName.toLowerCase()) === -1
-        ) {
-          return;
-        }
-
         const relatedComponent = utils.getRelatedComponent(node);
 
         if (
           relatedComponent &&
           (utils.isES6Component(relatedComponent.node) || utils.isReturningJSX(relatedComponent.node))
         ) {
+          const propertyName = node.property.name;
           reportErrorIfClassPropertyCasingTypo(node, propertyName);
         }
       },
diff --git a/lib/rules/no-unused-prop-types.js b/lib/rules/no-unused-prop-types.js
index b03e05a3..f595ce58 100644
--- a/lib/rules/no-unused-prop-types.js
+++ b/lib/rules/no-unused-prop-types.js
@@ -11,7 +11,6 @@ const has = require('has');
 const Components = require('../util/Components');
 const variable = require('../util/variable');
 const annotations = require('../util/annotations');
-const versionUtil = require('../util/version');
 
 // ------------------------------------------------------------------------------
 // Constants
@@ -134,48 +133,6 @@ module.exports = {
       return false;
     }
 
-    /**
-     * Resolve the type annotation for a given class declaration node with superTypeParameters.
-     *
-     * @param {ASTNode} node The annotation or a node containing the type annotation.
-     * @returns {ASTNode} The resolved type annotation for the node.
-     */
-    function resolveSuperParameterPropsType(node) {
-      let propsParameterPosition;
-      try {
-        // Flow <=0.52 had 3 required TypedParameters of which the second one is the Props.
-        // Flow >=0.53 has 2 optional TypedParameters of which the first one is the Props.
-        propsParameterPosition = versionUtil.testFlowVersion(context, '0.53.0') ? 0 : 1;
-      } catch (e) {
-        // In case there is no flow version defined, we can safely assume that when there are 3 Props we are dealing with version <= 0.52
-        propsParameterPosition = node.superTypeParameters.params.length <= 2 ? 0 : 1;
-      }
-
-      let annotation = node.superTypeParameters.params[propsParameterPosition];
-      while (annotation && (annotation.type === 'TypeAnnotation' || annotation.type === 'NullableTypeAnnotation')) {
-        annotation = annotation.typeAnnotation;
-      }
-      if (annotation.type === 'GenericTypeAnnotation' && typeScope(annotation.id.name)) {
-        return typeScope(annotation.id.name);
-      }
-      return annotation;
-    }
-
-    /**
-     * Checks if we are declaring a props as a generic type in a flow-annotated class.
-     *
-     * @param {ASTNode} node  the AST node being checked.
-     * @returns {Boolean} True if the node is a class with generic prop types, false if not.
-     */
-    function isSuperTypeParameterPropsDeclaration(node) {
-      if (node && node.type === 'ClassDeclaration') {
-        if (node.superTypeParameters && node.superTypeParameters.params.length > 0) {
-          return true;
-        }
-      }
-      return false;
-    }
-
     /**
      * Checks if we are declaring a prop
      * @param {ASTNode} node The AST node being checked.
@@ -301,14 +258,6 @@ module.exports = {
       return tokens.length && tokens[0].value === '...';
     }
 
-    /**
-     * Removes quotes from around an identifier.
-     * @param {string} the identifier to strip
-     */
-    function stripQuotes(string) {
-      return string.replace(/^\'|\'$/g, '');
-    }
-
     /**
      * Retrieve the name of a key node
      * @param {ASTNode} node The AST node with the key.
@@ -316,11 +265,8 @@ module.exports = {
      */
     function getKeyValue(node) {
       if (node.type === 'ObjectTypeProperty') {
-        const tokens = context.getFirstTokens(node, 2);
-        return (tokens[0].value === '+' || tokens[0].value === '-'
-          ? tokens[1].value
-          : stripQuotes(tokens[0].value)
-        );
+        const tokens = context.getFirstTokens(node, 1);
+        return tokens[0].value;
       }
       const key = node.key || node.argument;
       return key.type === 'Identifier' ? key.name : key.value;
@@ -359,7 +305,7 @@ module.exports = {
         value.callee.object &&
         hasCustomValidator(value.callee.object.name)
       ) {
-        return {};
+        return true;
       }
 
       if (
@@ -387,12 +333,12 @@ module.exports = {
         switch (callName) {
           case 'shape':
             if (skipShapeProps) {
-              return {};
+              return true;
             }
 
             if (argument.type !== 'ObjectExpression') {
               // Invalid proptype or cannot analyse statically
-              return {};
+              return true;
             }
             const shapeTypeDefinition = {
               type: 'shape',
@@ -400,7 +346,10 @@ module.exports = {
             };
             iterateProperties(argument.properties, (childKey, childValue) => {
               const fullName = [parentName, childKey].join('.');
-              const types = buildReactDeclarationTypes(childValue, fullName);
+              let types = buildReactDeclarationTypes(childValue, fullName);
+              if (types === true) {
+                types = {};
+              }
               types.fullName = fullName;
               types.name = childKey;
               types.node = childValue;
@@ -410,7 +359,10 @@ module.exports = {
           case 'arrayOf':
           case 'objectOf':
             const fullName = [parentName, '*'].join('.');
-            const child = buildReactDeclarationTypes(argument, fullName);
+            let child = buildReactDeclarationTypes(argument, fullName);
+            if (child === true) {
+              child = {};
+            }
             child.fullName = fullName;
             child.name = '__ANY_KEY__';
             child.node = argument;
@@ -424,7 +376,7 @@ module.exports = {
               !argument.elements.length
             ) {
               // Invalid proptype or cannot analyse statically
-              return {};
+              return true;
             }
             const unionTypeDefinition = {
               type: 'union',
@@ -433,7 +385,7 @@ module.exports = {
             for (let i = 0, j = argument.elements.length; i < j; i++) {
               const type = buildReactDeclarationTypes(argument.elements[i], parentName);
               // keep only complex type
-              if (Object.keys(type).length > 0) {
+              if (type !== true) {
                 if (type.children === true) {
                   // every child is accepted for one type, abort type analysis
                   unionTypeDefinition.children = true;
@@ -445,7 +397,7 @@ module.exports = {
             }
             if (unionTypeDefinition.length === 0) {
               // no complex type found, simply accept everything
-              return {};
+              return true;
             }
             return unionTypeDefinition;
           case 'instanceOf':
@@ -456,11 +408,11 @@ module.exports = {
             };
           case 'oneOf':
           default:
-            return {};
+            return true;
         }
       }
       // Unknown property or accepts everything (any, object, ...)
-      return {};
+      return true;
     }
 
     /**
@@ -468,7 +420,7 @@ module.exports = {
      * The representation is used to verify nested used properties.
      * @param {ASTNode} annotation Type annotation for the props class property.
      * @param {String} parentName Name of the parent prop node.
-     * @return {Object} The representation of the declaration, an empty object means
+     * @return {Object|Boolean} The representation of the declaration, true means
      *    the property is declared without the need for further analysis.
      */
     function buildTypeAnnotationDeclarationTypes(annotation, parentName) {
@@ -477,10 +429,10 @@ module.exports = {
           if (typeScope(annotation.id.name)) {
             return buildTypeAnnotationDeclarationTypes(typeScope(annotation.id.name), parentName);
           }
-          return {};
+          return true;
         case 'ObjectTypeAnnotation':
           if (skipShapeProps) {
-            return {};
+            return true;
           }
           const shapeTypeDefinition = {
             type: 'shape',
@@ -488,7 +440,10 @@ module.exports = {
           };
           iterateProperties(annotation.properties, (childKey, childValue) => {
             const fullName = [parentName, childKey].join('.');
-            const types = buildTypeAnnotationDeclarationTypes(childValue, fullName);
+            let types = buildTypeAnnotationDeclarationTypes(childValue, fullName);
+            if (types === true) {
+              types = {};
+            }
             types.fullName = fullName;
             types.name = childKey;
             types.node = childValue;
@@ -503,7 +458,7 @@ module.exports = {
           for (let i = 0, j = annotation.types.length; i < j; i++) {
             const type = buildTypeAnnotationDeclarationTypes(annotation.types[i], parentName);
             // keep only complex type
-            if (Object.keys(type).length > 0) {
+            if (type !== true) {
               if (type.children === true) {
                 // every child is accepted for one type, abort type analysis
                 unionTypeDefinition.children = true;
@@ -514,13 +469,16 @@ module.exports = {
             unionTypeDefinition.children.push(type);
           }
           if (unionTypeDefinition.children.length === 0) {
-            // no complex type found
-            return {};
+            // no complex type found, simply accept everything
+            return true;
           }
           return unionTypeDefinition;
         case 'ArrayTypeAnnotation':
           const fullName = [parentName, '*'].join('.');
-          const child = buildTypeAnnotationDeclarationTypes(annotation.elementType, fullName);
+          let child = buildTypeAnnotationDeclarationTypes(annotation.elementType, fullName);
+          if (child === true) {
+            child = {};
+          }
           child.fullName = fullName;
           child.name = '__ANY_KEY__';
           child.node = annotation;
@@ -530,7 +488,7 @@ module.exports = {
           };
         default:
           // Unknown or accepts everything.
-          return {};
+          return true;
       }
     }
 
@@ -712,60 +670,6 @@ module.exports = {
       });
     }
 
-    /**
-     * Marks all props found inside ObjectTypeAnnotaiton as declared.
-     * 
-     * Modifies the declaredProperties object
-     * @param {ASTNode} propTypes 
-     * @param {Object} declaredPropTypes 
-     * @returns {Boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported)
-     */
-    function declarePropTypesForObjectTypeAnnotation(propTypes, declaredPropTypes) {
-      let ignorePropsValidation = false;
-
-      iterateProperties(propTypes.properties, (key, value) => {
-        if (!value) {
-          ignorePropsValidation = true;
-          return;
-        }
-
-        const types = buildTypeAnnotationDeclarationTypes(value, key);
-        types.fullName = key;
-        types.name = key;
-        types.node = value;
-        declaredPropTypes.push(types);
-      });
-
-      return ignorePropsValidation;
-    }
-
-    /**
-     * Marks all props found inside IntersectionTypeAnnotation as declared.
-     * Since InterSectionTypeAnnotations can be nested, this handles recursively. 
-     * 
-     * Modifies the declaredPropTypes object
-     * @param {ASTNode} propTypes 
-     * @param {Object} declaredPropTypes 
-     * @returns {Boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported)
-     */
-    function declarePropTypesForIntersectionTypeAnnotation(propTypes, declaredPropTypes) {
-      return propTypes.types.some(annotation => {
-        if (annotation.type === 'ObjectTypeAnnotation') {
-          return declarePropTypesForObjectTypeAnnotation(annotation, declaredPropTypes);
-        }
-
-        const typeNode = typeScope(annotation.id.name);
-
-        if (!typeNode) {
-          return true;
-        } else if (typeNode.type === 'IntersectionTypeAnnotation') {
-          return declarePropTypesForIntersectionTypeAnnotation(typeNode, declaredPropTypes);
-        }
-
-        return declarePropTypesForObjectTypeAnnotation(typeNode, declaredPropTypes);
-      });
-    }
-
     /**
      * Mark a prop type as declared
      * @param {ASTNode} node The AST node being checked.
@@ -778,7 +682,20 @@ module.exports = {
 
       switch (propTypes && propTypes.type) {
         case 'ObjectTypeAnnotation':
-          ignorePropsValidation = declarePropTypesForObjectTypeAnnotation(propTypes, declaredPropTypes);
+          iterateProperties(propTypes.properties, (key, value) => {
+            if (!value) {
+              ignorePropsValidation = true;
+              return;
+            }
+            let types = buildTypeAnnotationDeclarationTypes(value, key);
+            if (types === true) {
+              types = {};
+            }
+            types.fullName = key;
+            types.name = key;
+            types.node = value;
+            declaredPropTypes.push(types);
+          });
           break;
         case 'ObjectExpression':
           iterateProperties(propTypes.properties, (key, value) => {
@@ -786,7 +703,10 @@ module.exports = {
               ignorePropsValidation = true;
               return;
             }
-            const types = buildReactDeclarationTypes(value, key);
+            let types = buildReactDeclarationTypes(value, key);
+            if (types === true) {
+              types = {};
+            }
             types.fullName = key;
             types.name = key;
             types.node = value;
@@ -816,9 +736,6 @@ module.exports = {
             return;
           }
           break;
-        case 'IntersectionTypeAnnotation':
-          ignorePropsValidation = declarePropTypesForIntersectionTypeAnnotation(propTypes, declaredPropTypes);
-          break;
         case null:
           break;
         default:
@@ -929,12 +846,6 @@ module.exports = {
     // --------------------------------------------------------------------------
 
     return {
-      ClassDeclaration: function(node) {
-        if (isSuperTypeParameterPropsDeclaration(node)) {
-          markPropTypesAsDeclared(node, resolveSuperParameterPropsType(node));
-        }
-      },
-
       ClassProperty: function(node) {
         if (isAnnotatedClassPropsDeclaration(node)) {
           markPropTypesAsDeclared(node, resolveTypeAnnotation(node));
diff --git a/lib/rules/no-unused-state.js b/lib/rules/no-unused-state.js
index d4bef8c2..41f333af 100644
--- a/lib/rules/no-unused-state.js
+++ b/lib/rules/no-unused-state.js
@@ -25,14 +25,10 @@ function uncast(node) {
 // method definitions, ObjectExpression property keys).
 function getName(node) {
   node = uncast(node);
-  const type = node.type;
-
-  if (type === 'Identifier') {
+  if (node.type === 'Identifier') {
     return node.name;
-  } else if (type === 'Literal') {
+  } else if (node.type === 'Literal') {
     return String(node.value);
-  } else if (type === 'TemplateLiteral' && node.expressions.length === 0) {
-    return node.quasis[0].value.raw;
   }
   return null;
 }
@@ -96,15 +92,7 @@ module.exports = {
     // current set of state fields.
     function addStateFields(node) {
       for (const prop of node.properties) {
-        const key = prop.key;
-
-        if (
-          prop.type === 'Property' &&
-          (key.type === 'Literal' ||
-          (key.type === 'TemplateLiteral' && key.expressions.length === 0) ||
-          (prop.computed === false && key.type === 'Identifier')) &&
-          getName(prop.key) !== null
-        ) {
+        if (prop.type === 'Property' && getName(prop.key) !== null) {
           classInfo.stateFields.add(prop);
         }
       }
diff --git a/lib/rules/prefer-stateless-function.js b/lib/rules/prefer-stateless-function.js
index e3c4ff52..5e897245 100644
--- a/lib/rules/prefer-stateless-function.js
+++ b/lib/rules/prefer-stateless-function.js
@@ -371,7 +371,7 @@ module.exports = {
           scope = scope.upper;
         }
         const isRender = blockNode && blockNode.key && blockNode.key.name === 'render';
-        const allowNull = versionUtil.testReactVersion(context, '15.0.0'); // Stateless components can return null since React 15
+        const allowNull = versionUtil.test(context, '15.0.0'); // Stateless components can return null since React 15
         const isReturningJSX = utils.isReturningJSX(node, !allowNull);
         const isReturningNull = node.argument && (node.argument.value === null || node.argument.value === false);
         if (
diff --git a/lib/rules/prop-types.js b/lib/rules/prop-types.js
index aff75086..32b83ed6 100644
--- a/lib/rules/prop-types.js
+++ b/lib/rules/prop-types.js
@@ -11,7 +11,6 @@ const has = require('has');
 const Components = require('../util/Components');
 const variable = require('../util/variable');
 const annotations = require('../util/annotations');
-const versionUtil = require('../util/version');
 
 // ------------------------------------------------------------------------------
 // Constants
@@ -65,7 +64,6 @@ module.exports = {
     // Used to track the type annotations in scope.
     // Necessary because babel's scopes do not track type annotations.
     let stack = null;
-    const classExpressions = [];
 
     const MISSING_MESSAGE = '\'{{name}}\' is missing in props validation';
 
@@ -118,20 +116,6 @@ module.exports = {
       return false;
     }
 
-    /**
-    * Checks if a prop is being assigned a value props.bar = 'bar'
-    * @param {ASTNode} node The AST node being checked.
-    * @returns {Boolean}
-    */
-
-    function isAssignmentToProp(node) {
-      return (
-        node.parent &&
-        node.parent.type === 'AssignmentExpression' &&
-        node.parent.left === node
-      );
-    }
-
     /**
      * Checks if we are using a prop
      * @param {ASTNode} node The AST node being checked.
@@ -142,7 +126,7 @@ module.exports = {
         (utils.getParentES6Component() || utils.getParentES5Component()) &&
         node.object.type === 'ThisExpression' && node.property.name === 'props'
       );
-      const isStatelessFunctionUsage = node.object.name === 'props' && !isAssignmentToProp(node);
+      const isStatelessFunctionUsage = node.object.name === 'props';
       const isNextPropsUsage = node.object.name === 'nextProps' && inComponentWillReceiveProps();
       return isClassUsage || isStatelessFunctionUsage || isNextPropsUsage;
     }
@@ -174,8 +158,8 @@ module.exports = {
      * @returns {Boolean} True if the node is a class with generic prop types, false if not.
      */
     function isSuperTypeParameterPropsDeclaration(node) {
-      if (node && (node.type === 'ClassDeclaration' || node.type === 'ClassExpression')) {
-        if (node.superTypeParameters && node.superTypeParameters.params.length > 0) {
+      if (node && node.type === 'ClassDeclaration') {
+        if (node.superTypeParameters && node.superTypeParameters.params.length >= 2) {
           return true;
         }
       }
@@ -249,7 +233,6 @@ module.exports = {
     function _isDeclaredInComponent(declaredPropTypes, keyList) {
       for (let i = 0, j = keyList.length; i < j; i++) {
         const key = keyList[i];
-
         const propType = (
           declaredPropTypes && (
             // Check if this key is declared
@@ -262,7 +245,7 @@ module.exports = {
           // If it's a computed property, we can't make any further analysis, but is valid
           return key === '__COMPUTED_PROP__';
         }
-        if (typeof propType === 'object' && Object.keys(propType).length === 0) {
+        if (propType === true) {
           return true;
         }
         // Consider every children as declared
@@ -309,7 +292,6 @@ module.exports = {
     function isDeclaredInComponent(node, names) {
       while (node) {
         const component = components.get(node);
-
         const isDeclared =
           component && component.confidence === 2 &&
           _isDeclaredInComponent(component.declaredPropTypes || {}, names)
@@ -337,7 +319,10 @@ module.exports = {
      * @param {string} the identifier to strip
      */
     function stripQuotes(string) {
-      return string.replace(/^\'|\'$/g, '');
+      if (string[0] === '\'' || string[0] === '"' && string[0] === string[string.length - 1]) {
+        return string.slice(1, string.length - 1);
+      }
+      return string;
     }
 
     /**
@@ -379,7 +364,7 @@ module.exports = {
      * Creates the representation of the React propTypes for the component.
      * The representation is used to verify nested used properties.
      * @param {ASTNode} value Node of the PropTypes for the desired property
-     * @return {Object} The representation of the declaration, empty object means
+     * @return {Object|Boolean} The representation of the declaration, true means
      *    the property is declared without the need for further analysis.
      */
     function buildReactDeclarationTypes(value) {
@@ -389,7 +374,7 @@ module.exports = {
         value.callee.object &&
         hasCustomValidator(value.callee.object.name)
       ) {
-        return {};
+        return true;
       }
 
       if (
@@ -418,7 +403,7 @@ module.exports = {
           case 'shape':
             if (argument.type !== 'ObjectExpression') {
               // Invalid proptype or cannot analyse statically
-              return {};
+              return true;
             }
             const shapeTypeDefinition = {
               type: 'shape',
@@ -442,7 +427,7 @@ module.exports = {
               !argument.elements.length
             ) {
               // Invalid proptype or cannot analyse statically
-              return {};
+              return true;
             }
             const unionTypeDefinition = {
               type: 'union',
@@ -451,7 +436,7 @@ module.exports = {
             for (let i = 0, j = argument.elements.length; i < j; i++) {
               const type = buildReactDeclarationTypes(argument.elements[i]);
               // keep only complex type
-              if (Object.keys(type).length > 0) {
+              if (type !== true) {
                 if (type.children === true) {
                   // every child is accepted for one type, abort type analysis
                   unionTypeDefinition.children = true;
@@ -463,7 +448,7 @@ module.exports = {
             }
             if (unionTypeDefinition.length === 0) {
               // no complex type found, simply accept everything
-              return {};
+              return true;
             }
             return unionTypeDefinition;
           case 'instanceOf':
@@ -474,18 +459,18 @@ module.exports = {
             };
           case 'oneOf':
           default:
-            return {};
+            return true;
         }
       }
       // Unknown property or accepts everything (any, object, ...)
-      return {};
+      return true;
     }
 
     /**
      * Creates the representation of the React props type annotation for the component.
      * The representation is used to verify nested used properties.
      * @param {ASTNode} annotation Type annotation for the props class property.
-     * @return {Object} The representation of the declaration, empty object means
+     * @return {Object|Boolean} The representation of the declaration, true means
      *    the property is declared without the need for further analysis.
      */
     function buildTypeAnnotationDeclarationTypes(annotation) {
@@ -494,7 +479,7 @@ module.exports = {
           if (typeScope(annotation.id.name)) {
             return buildTypeAnnotationDeclarationTypes(typeScope(annotation.id.name));
           }
-          return {};
+          return true;
         case 'ObjectTypeAnnotation':
           let containsObjectTypeSpread = false;
           const shapeTypeDefinition = {
@@ -511,7 +496,7 @@ module.exports = {
 
           // nested object type spread means we need to ignore/accept everything in this object
           if (containsObjectTypeSpread) {
-            return {};
+            return true;
           }
           return shapeTypeDefinition;
         case 'UnionTypeAnnotation':
@@ -522,7 +507,7 @@ module.exports = {
           for (let i = 0, j = annotation.types.length; i < j; i++) {
             const type = buildTypeAnnotationDeclarationTypes(annotation.types[i]);
             // keep only complex type
-            if (Object.keys(type).length > 0) {
+            if (type !== true) {
               if (type.children === true) {
                 // every child is accepted for one type, abort type analysis
                 unionTypeDefinition.children = true;
@@ -534,7 +519,7 @@ module.exports = {
           }
           if (unionTypeDefinition.children.length === 0) {
             // no complex type found, simply accept everything
-            return {};
+            return true;
           }
           return unionTypeDefinition;
         case 'ArrayTypeAnnotation':
@@ -546,7 +531,7 @@ module.exports = {
           };
         default:
           // Unknown or accepts everything.
-          return {};
+          return true;
       }
     }
 
@@ -712,56 +697,6 @@ module.exports = {
       });
     }
 
-    /**
-     * Marks all props found inside ObjectTypeAnnotaiton as declared.
-     * 
-     * Modifies the declaredProperties object
-     * @param {ASTNode} propTypes 
-     * @param {Object} declaredPropTypes 
-     * @returns {Boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported)
-     */
-    function declarePropTypesForObjectTypeAnnotation(propTypes, declaredPropTypes) {
-      let ignorePropsValidation = false;
-
-      iterateProperties(propTypes.properties, (key, value) => {
-        if (!value) {
-          ignorePropsValidation = true;
-          return;
-        }
-
-        declaredPropTypes[key] = buildTypeAnnotationDeclarationTypes(value);
-      });
-
-      return ignorePropsValidation;
-    }
-
-    /**
-     * Marks all props found inside IntersectionTypeAnnotation as declared.
-     * Since InterSectionTypeAnnotations can be nested, this handles recursively. 
-     * 
-     * Modifies the declaredPropTypes object
-     * @param {ASTNode} propTypes 
-     * @param {Object} declaredPropTypes 
-     * @returns {Boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported)
-     */
-    function declarePropTypesForIntersectionTypeAnnotation(propTypes, declaredPropTypes) {
-      return propTypes.types.some(annotation => {
-        if (annotation.type === 'ObjectTypeAnnotation') {
-          return declarePropTypesForObjectTypeAnnotation(annotation, declaredPropTypes);
-        }
-
-        const typeNode = typeScope(annotation.id.name);
-
-        if (!typeNode) {
-          return true;
-        } else if (typeNode.type === 'IntersectionTypeAnnotation') {
-          return declarePropTypesForIntersectionTypeAnnotation(typeNode, declaredPropTypes);
-        }
-
-        return declarePropTypesForObjectTypeAnnotation(typeNode, declaredPropTypes);
-      });
-    }
-
     /**
      * Mark a prop type as declared
      * @param {ASTNode} node The AST node being checked.
@@ -778,7 +713,13 @@ module.exports = {
 
       switch (propTypes && propTypes.type) {
         case 'ObjectTypeAnnotation':
-          ignorePropsValidation = declarePropTypesForObjectTypeAnnotation(propTypes, declaredPropTypes);
+          iterateProperties(propTypes.properties, (key, value) => {
+            if (!value) {
+              ignorePropsValidation = true;
+              return;
+            }
+            declaredPropTypes[key] = buildTypeAnnotationDeclarationTypes(value);
+          });
           break;
         case 'ObjectExpression':
           iterateProperties(propTypes.properties, (key, value) => {
@@ -831,16 +772,13 @@ module.exports = {
           break;
         case 'CallExpression':
           if (
-            propWrapperFunctions.has(sourceCode.getText(propTypes.callee)) &&
+            propWrapperFunctions.has(propTypes.callee.name) &&
             propTypes.arguments && propTypes.arguments[0]
           ) {
             markPropTypesAsDeclared(node, propTypes.arguments[0]);
             return;
           }
           break;
-        case 'IntersectionTypeAnnotation':
-          ignorePropsValidation = declarePropTypesForIntersectionTypeAnnotation(propTypes, declaredPropTypes);
-          break;
         case null:
           break;
         default:
@@ -905,21 +843,10 @@ module.exports = {
      * @returns {ASTNode} The resolved type annotation for the node.
      */
     function resolveSuperParameterPropsType(node) {
-      let propsParameterPosition;
-      try {
-        // Flow <=0.52 had 3 required TypedParameters of which the second one is the Props.
-        // Flow >=0.53 has 2 optional TypedParameters of which the first one is the Props.
-        propsParameterPosition = versionUtil.testFlowVersion(context, '0.53.0') ? 0 : 1;
-      } catch (e) {
-        // In case there is no flow version defined, we can safely assume that when there are 3 Props we are dealing with version <= 0.52
-        propsParameterPosition = node.superTypeParameters.params.length <= 2 ? 0 : 1;
-      }
-
-      let annotation = node.superTypeParameters.params[propsParameterPosition];
+      let annotation = node.superTypeParameters.params[1];
       while (annotation && (annotation.type === 'TypeAnnotation' || annotation.type === 'NullableTypeAnnotation')) {
         annotation = annotation.typeAnnotation;
       }
-
       if (annotation.type === 'GenericTypeAnnotation' && typeScope(annotation.id.name)) {
         return typeScope(annotation.id.name);
       }
@@ -968,13 +895,6 @@ module.exports = {
         }
       },
 
-      ClassExpression: function(node) {
-        // TypeParameterDeclaration need to be added to typeScope in order to handle ClassExpressions.
-        // This visitor is executed before TypeParameterDeclaration are scoped, therefore we postpone
-        // processing class expressions until when the program exists.
-        classExpressions.push(node);
-      },
-
       ClassProperty: function(node) {
         if (isAnnotatedClassPropsDeclaration(node)) {
           markPropTypesAsDeclared(node, resolveTypeAnnotation(node));
@@ -1066,14 +986,6 @@ module.exports = {
         typeScope(node.id.name, node.right);
       },
 
-      TypeParameterDeclaration: function(node) {
-        const identifier = node.params[0];
-
-        if (identifier.typeAnnotation) {
-          typeScope(identifier.name, identifier.typeAnnotation.typeAnnotation);
-        }
-      },
-
       Program: function() {
         stack = [{}];
       },
@@ -1087,12 +999,6 @@ module.exports = {
       },
 
       'Program:exit': function() {
-        classExpressions.forEach(node => {
-          if (isSuperTypeParameterPropsDeclaration(node)) {
-            markPropTypesAsDeclared(node, resolveSuperParameterPropsType(node));
-          }
-        });
-
         stack = null;
         const list = components.list();
         // Report undeclared proptypes for all classes
diff --git a/lib/rules/require-default-props.js b/lib/rules/require-default-props.js
index 4d8cdf9e..58a0ef2e 100644
--- a/lib/rules/require-default-props.js
+++ b/lib/rules/require-default-props.js
@@ -109,7 +109,7 @@ module.exports = {
         propWrapperFunctions.has(node.callee.name) &&
         node.arguments && node.arguments[0]
       ) {
-        return resolveNodeValue(node.arguments[0]);
+        return node.arguments[0];
       }
 
       return node;
@@ -578,7 +578,7 @@ module.exports = {
 
           // If no propTypes could be found, we don't report anything.
           if (!list[component].propTypes) {
-            continue;
+            return;
           }
 
           reportPropTypesWithoutDefault(
diff --git a/lib/rules/sort-prop-types.js b/lib/rules/sort-prop-types.js
index 15038090..62f27968 100644
--- a/lib/rules/sort-prop-types.js
+++ b/lib/rules/sort-prop-types.js
@@ -78,25 +78,6 @@ module.exports = {
       return getValueName(node) === 'isRequired';
     }
 
-    /**
-     * Find a variable by name in the current scope.
-     * @param  {string} name Name of the variable to look for.
-     * @returns {ASTNode|null} Return null if the variable could not be found, ASTNode otherwise.
-     */
-    function findVariableByName(name) {
-      const variable = variableUtil.variablesInScope(context).find(item => item.name === name);
-
-      if (!variable || !variable.defs[0] || !variable.defs[0].node) {
-        return null;
-      }
-
-      if (variable.defs[0].node.type === 'TypeAlias') {
-        return variable.defs[0].node.right;
-      }
-
-      return variable.defs[0].node.init;
-    }
-
     /**
      * Checks if propTypes declarations are sorted
      * @param {Array} declarations The array of AST nodes being checked.
@@ -162,42 +143,62 @@ module.exports = {
       }, declarations[0]);
     }
 
-    function checkNode(node) {
-      switch (node && node.type) {
-        case 'ObjectExpression':
-          checkSorted(node.properties);
-          break;
-        case 'Identifier':
-          const propTypesObject = findVariableByName(node.name);
-          if (propTypesObject && propTypesObject.properties) {
-            checkSorted(propTypesObject.properties);
-          }
-          break;
-        case 'CallExpression':
-          const innerNode = node.arguments && node.arguments[0];
-          if (propWrapperFunctions.has(node.callee.name) && innerNode) {
-            checkNode(innerNode);
-          }
-          break;
-        default:
-          break;
-      }
-    }
-
     return {
       ClassProperty: function(node) {
         if (!isPropTypesDeclaration(node)) {
           return;
         }
-        checkNode(node.value);
+        switch (node.value && node.value.type) {
+          case 'ObjectExpression':
+            checkSorted(node.value.properties);
+            break;
+          case 'CallExpression':
+            if (
+              propWrapperFunctions.has(node.value.callee.name) &&
+              node.value.arguments && node.value.arguments[0]
+            ) {
+              checkSorted(node.value.arguments[0].properties);
+            }
+            break;
+          default:
+            break;
+        }
       },
 
       MemberExpression: function(node) {
         if (!isPropTypesDeclaration(node.property)) {
           return;
         }
-
-        checkNode(node.parent.right);
+        const right = node.parent.right;
+        let declarations;
+        switch (right && right.type) {
+          case 'CallExpression':
+            if (
+              propWrapperFunctions.has(right.callee.name) &&
+              right.arguments && right.arguments[0]
+            ) {
+              declarations = right.arguments[0].properties;
+            }
+            break;
+          case 'ObjectExpression':
+            declarations = right.properties;
+            break;
+          case 'Identifier':
+            const variable = variableUtil.variablesInScope(context).find(item => item.name === right.name);
+            if (
+              !variable || !variable.defs[0] ||
+              !variable.defs[0].node.init || !variable.defs[0].node.init.properties
+            ) {
+              break;
+            }
+            declarations = variable.defs[0].node.init.properties;
+            break;
+          default:
+            break;
+        }
+        if (declarations) {
+          checkSorted(declarations);
+        }
       },
 
       ObjectExpression: function(node) {
diff --git a/lib/util/Components.js b/lib/util/Components.js
index b25bcce3..1311fd9f 100644
--- a/lib/util/Components.js
+++ b/lib/util/Components.js
@@ -215,16 +215,7 @@ function componentRule(rule, context) {
      * @returns {Boolean} True if the node is explicitly declared as a descendant of a React Component, false if not
      */
     isExplicitComponent: function(node) {
-      let comment;
-      // Sometimes the passed node may not have been parsed yet by eslint, and this function call crashes.
-      // Can be removed when eslint sets "parent" property for all nodes on initial AST traversal: https://github.com/eslint/eslint-scope/issues/27
-      // eslint-disable-next-line no-warning-comments
-      // FIXME: Remove try/catch when https://github.com/eslint/eslint-scope/issues/27 is implemented.
-      try {
-        comment = sourceCode.getJSDocComment(node);
-      } catch (e) {
-        comment = null;
-      }
+      const comment = sourceCode.getJSDocComment(node);
 
       if (comment === null) {
         return false;
@@ -537,7 +528,7 @@ function componentRule(rule, context) {
           continue;
         }
         for (k = 0, l = componentNode.properties.length; k < l; k++) {
-          if (componentNode.properties[k].key && componentNode.properties[k].key.name === componentPath[i]) {
+          if (componentNode.properties[k].key.name === componentPath[i]) {
             componentNode = componentNode.properties[k];
             break;
           }
diff --git a/lib/util/version.js b/lib/util/version.js
index cbdec7d9..a3847fd1 100644
--- a/lib/util/version.js
+++ b/lib/util/version.js
@@ -1,10 +1,10 @@
 /**
- * @fileoverview Utility functions for React and Flow version configuration
+ * @fileoverview Utility functions for React version configuration
  * @author Yannick Croissant
  */
 'use strict';
 
-function getReactVersionFromContext(context) {
+function getFromContext(context) {
   let confVer = '999.999.999';
   // .eslintrc shared settings (http://eslint.org/docs/user-guide/configuring#adding-shared-settings)
   if (context.settings.react && context.settings.react.version) {
@@ -14,19 +14,8 @@ function getReactVersionFromContext(context) {
   return confVer.split('.').map(part => Number(part));
 }
 
-function getFlowVersionFromContext(context) {
-  let confVer = '999.999.999';
-  // .eslintrc shared settings (http://eslint.org/docs/user-guide/configuring#adding-shared-settings)
-  if (context.settings.react && context.settings.react.flowVersion) {
-    confVer = context.settings.react.flowVersion;
-  } else {
-    throw 'Could not retrieve flowVersion from settings';
-  }
-  confVer = /^[0-9]+\.[0-9]+$/.test(confVer) ? `${confVer}.0` : confVer;
-  return confVer.split('.').map(part => Number(part));
-}
-
-function test(context, methodVer, confVer) {
+function test(context, methodVer) {
+  const confVer = getFromContext(context);
   methodVer = methodVer.split('.').map(part => Number(part));
   const higherMajor = methodVer[0] < confVer[0];
   const higherMinor = methodVer[0] === confVer[0] && methodVer[1] < confVer[1];
@@ -35,15 +24,6 @@ function test(context, methodVer, confVer) {
   return higherMajor || higherMinor || higherOrEqualPatch;
 }
 
-function testReactVersion(context, methodVer) {
-  return test(context, methodVer, getReactVersionFromContext(context));
-}
-
-function testFlowVersion(context, methodVer) {
-  return test(context, methodVer, getFlowVersionFromContext(context));
-}
-
 module.exports = {
-  testReactVersion,
-  testFlowVersion
+  test: test
 };
diff --git a/package.json b/package.json
index 1ed552a7..c1a52caa 100644
--- a/package.json
+++ b/package.json
@@ -1,14 +1,13 @@
 {
   "name": "eslint-plugin-react",
-  "version": "7.4.0",
+  "version": "7.1.0",
   "author": "Yannick Croissant <yannick.croissant+npm@gmail.com>",
   "description": "React specific linting rules for ESLint",
   "main": "index.js",
   "scripts": {
     "coveralls": "cat ./reports/coverage/lcov.info | coveralls",
     "lint": "eslint ./",
-    "pretest": "npm run lint",
-    "test": "npm run unit-test",
+    "test": "npm run lint && npm run unit-test",
     "unit-test": "istanbul cover --dir reports/coverage node_modules/mocha/bin/_mocha tests/**/*.js -- --reporter dot"
   },
   "files": [
@@ -26,8 +25,7 @@
   "dependencies": {
     "doctrine": "^2.0.0",
     "has": "^1.0.1",
-    "jsx-ast-utils": "^2.0.0",
-    "prop-types": "^15.5.10"
+    "jsx-ast-utils": "^2.0.0"
   },
   "devDependencies": {
     "babel-eslint": "^7.2.3",


Test patch:
diff --git a/tests/lib/rules/boolean-prop-naming.js b/tests/lib/rules/boolean-prop-naming.js
index 6e10971e..6945bc1b 100644
--- a/tests/lib/rules/boolean-prop-naming.js
+++ b/tests/lib/rules/boolean-prop-naming.js
@@ -1,6 +1,6 @@
 /**
  * @fileoverview Enforces consistent naming for boolean props
- * @author Ev Haus
+ * @author Evgueni Naverniouk
  */
 'use strict';
 
@@ -101,16 +101,6 @@ ruleTester.run('boolean-prop-naming', rule, {
     options: [{
       rule: '^is[A-Z]([A-Za-z0-9]?)+'
     }]
-  }, {
-    code: [
-      'class Hello extends React.Component {',
-      '  render () { return <div />; }',
-      '}',
-      'Hello.propTypes = wrap({ a: PropTypes.bool })'
-    ].join('\n'),
-    options: [{
-      rule: '^is[A-Z]([A-Za-z0-9]?)+'
-    }]
   }, {
     // ES6 components as React.Component with non-boolean PropTypes
     code: [
@@ -247,28 +237,6 @@ ruleTester.run('boolean-prop-naming', rule, {
       rule: '^is[A-Z]([A-Za-z0-9]?)+'
     }],
     parser: 'babel-eslint'
-  }, {
-    // Ensure rule doesn't crash on destructured objects [Issue #1369]
-    code: [
-      'var x = {a: 1}',
-      'var y = {...x}'
-    ].join('\n'),
-    options: [{
-      rule: '^is[A-Z]([A-Za-z0-9]?)+'
-    }],
-    parser: 'babel-eslint'
-  }, {
-    // Ensure rule doesn't crash on on components reference old-style Flow props
-    code: [
-      'class Hello extends PureComponent {',
-      '  props: PropsType;',
-      '  render () { return <div /> }',
-      '}'
-    ].join('\n'),
-    options: [{
-      rule: '^is[A-Z]([A-Za-z0-9]?)+'
-    }],
-    parser: 'babel-eslint'
   }],
 
   invalid: [{
diff --git a/tests/lib/rules/default-props-match-prop-types.js b/tests/lib/rules/default-props-match-prop-types.js
index 52a64fa1..e7684558 100644
--- a/tests/lib/rules/default-props-match-prop-types.js
+++ b/tests/lib/rules/default-props-match-prop-types.js
@@ -682,25 +682,6 @@ ruleTester.run('default-props-match-prop-types', rule, {
       ].join('\n'),
       parser: 'babel-eslint'
     },
-    {
-      code: `
-        type PropsA = { foo?: string };
-        type PropsB = { bar?: string, fooBar: string };
-        type Props = PropsA & PropsB;
-
-        class Bar extends React.Component {
-          props: Props;
-          static defaultProps = {
-            foo: "foo",
-          }
-
-          render() {
-            return <div>{this.props.foo} - {this.props.bar}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    },
     {
       code: [
         'import type Props from "fake";',
@@ -802,29 +783,6 @@ ruleTester.run('default-props-match-prop-types', rule, {
         column: 3
       }]
     },
-    {
-      code: [
-        'function MyStatelessComponent({ foo, bar }) {',
-        '  return <div>{foo}{bar}</div>;',
-        '}',
-        'const propTypes = {',
-        '  foo: React.PropTypes.string,',
-        '  bar: React.PropTypes.string.isRequired',
-        '};',
-        'MyStatelessComponent.propTypes = forbidExtraProps(propTypes);',
-        'MyStatelessComponent.defaultProps = {',
-        '  baz: "baz"',
-        '};'
-      ].join('\n'),
-      settings: {
-        propWrapperFunctions: ['forbidExtraProps']
-      },
-      errors: [{
-        message: 'defaultProp "baz" has no corresponding propTypes declaration.',
-        line: 10,
-        column: 3
-      }]
-    },
     {
       code: [
         'function MyStatelessComponent({ foo, bar }) {',
@@ -1528,34 +1486,6 @@ ruleTester.run('default-props-match-prop-types', rule, {
           column: 36
         }
       ]
-    },
-    {
-      code: `
-        type PropsA = { foo: string };
-        type PropsB = { bar: string };
-        type Props = PropsA & PropsB;
-
-        class Bar extends React.Component {
-          props: Props;
-          static defaultProps = {
-            fooBar: "fooBar",
-            foo: "foo",
-          }
-
-          render() {
-            return <div>{this.props.foo} - {this.props.bar}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint',
-      errors: [
-        {
-          message: 'defaultProp "fooBar" has no corresponding propTypes declaration.'
-        },
-        {
-          message: 'defaultProp "foo" defined for isRequired propType.'
-        }
-      ]
     }
   ]
 });
diff --git a/tests/lib/rules/forbid-prop-types.js b/tests/lib/rules/forbid-prop-types.js
index e6c7eb3b..604509be 100644
--- a/tests/lib/rules/forbid-prop-types.js
+++ b/tests/lib/rules/forbid-prop-types.js
@@ -398,25 +398,6 @@ ruleTester.run('forbid-prop-types', rule, {
     settings: {
       propWrapperFunctions: ['forbidExtraProps']
     }
-  }, {
-    code: [
-      'import { forbidExtraProps } from "airbnb-prop-types";',
-      'export const propTypes = {dpm: PropTypes.any};',
-      'export default function Component() {}',
-      'Component.propTypes = propTypes;'
-    ].join('\n'),
-    errors: [{message: ANY_ERROR_MESSAGE}]
-  }, {
-    code: [
-      'import { forbidExtraProps } from "airbnb-prop-types";',
-      'export const propTypes = {a: PropTypes.any};',
-      'export default function Component() {}',
-      'Component.propTypes = forbidExtraProps(propTypes);'
-    ].join('\n'),
-    errors: [{message: ANY_ERROR_MESSAGE}],
-    settings: {
-      propWrapperFunctions: ['forbidExtraProps']
-    }
   }, {
     code: [
       'class Component extends React.Component {',
diff --git a/tests/lib/rules/jsx-curly-brace-presence.js b/tests/lib/rules/jsx-curly-brace-presence.js
deleted file mode 100644
index 1ae02da4..00000000
--- a/tests/lib/rules/jsx-curly-brace-presence.js
+++ /dev/null
@@ -1,393 +0,0 @@
-/**
- * @fileoverview Enforce curly braces or disallow unnecessary curly braces in JSX
- * @author Jacky Ho
- */
-'use strict';
-
-// ------------------------------------------------------------------------------
-// Requirements
-// ------------------------------------------------------------------------------
-
-const rule = require('../../../lib/rules/jsx-curly-brace-presence');
-const RuleTester = require('eslint').RuleTester;
-const parserOptions = {
-  sourceType: 'module',
-  ecmaFeatures: {
-    jsx: true
-  }
-};
-
-const missingCurlyMessage = 'Need to wrap this literal in a JSX expression.';
-const unnecessaryCurlyMessage = 'Curly braces are unnecessary here.';
-
-// ------------------------------------------------------------------------------
-// Tests
-// ------------------------------------------------------------------------------
-
-const ruleTester = new RuleTester({parserOptions});
-ruleTester.run('jsx-curly-brace-presence', rule, {
-  valid: [
-    {
-      code: '<App {...props}>foo</App>'
-    },
-    {
-      code: '<App {...props}>foo</App>',
-      options: [{props: 'never'}]
-    },
-    {
-      code: '<App {...props}>foo</App>',
-      options: [{props: 'always'}]
-    },
-    {
-      code: '<App>{`Hello ${word} World`}</App>',
-      options: [{children: 'never'}]
-    },
-    {
-      code: '<App>{`Hello \\n World`}</App>',
-      options: [{children: 'never'}]
-    },
-    {
-      code: '<App>{`Hello ${word} World`}{`foo`}</App>',
-      options: [{children: 'never'}]
-    },
-    {
-      code: '<App prop={`foo ${word} bar`}>foo</App>',
-      options: [{props: 'never'}]
-    },
-    {
-      code: '<App prop={`foo ${word} bar`} />',
-      options: [{props: 'never'}]
-    },
-    {
-      code: '<App>{<myApp></myApp>}</App>'
-    },
-    {
-      code: '<App>{[]}</App>'
-    },
-    {
-      code: '<App>foo</App>'
-    },
-    {
-      code: '<App>{"foo"}{<Component>bar</Component>}</App>'
-    },
-    {
-      code: '<App prop=\'bar\'>foo</App>'
-    },
-    {
-      code: '<App prop={true}>foo</App>'
-    },
-    {
-      code: '<App prop>foo</App>'
-    },
-    {
-      code: '<App prop=\'bar\'>{\'foo \\n bar\'}</App>'
-    },
-    {
-      code: '<MyComponent prop=\'bar\'>foo</MyComponent>',
-      options: [{props: 'never'}]
-    },
-    {
-      code: '<MyComponent prop=\"bar\">foo</MyComponent>',
-      options: [{props: 'never'}]
-    },
-    {
-      code: '<MyComponent>foo</MyComponent>',
-      options: [{children: 'never'}]
-    },
-    {
-      code: '<MyComponent>{<App/>}{"123"}</MyComponent>',
-      options: [{children: 'never'}]
-    },
-    {
-      code: '<App>{\"foo \'bar\' \\\"foo\\\" bar\"}</App>',
-      options: [{children: 'never'}]
-    },
-    {
-      code: '<MyComponent prop={\'bar\'}>foo</MyComponent>',
-      options: [{props: 'always'}]
-    },
-    {
-      code: '<MyComponent>{\'foo\'}</MyComponent>',
-      options: [{children: 'always'}]
-    },
-    {
-      code: '<MyComponent prop={\"bar\"}>foo</MyComponent>',
-      options: [{props: 'always'}]
-    },
-    {
-      code: '<MyComponent>{\"foo\"}</MyComponent>',
-      options: [{children: 'always'}]
-    },
-    {
-      code: '<MyComponent>{\'foo\'}</MyComponent>',
-      options: [{children: 'ignore'}]
-    },
-    {
-      code: '<MyComponent prop={\'bar\'}>foo</MyComponent>',
-      options: [{props: 'ignore'}]
-    },
-    {
-      code: '<MyComponent>foo</MyComponent>',
-      options: [{children: 'ignore'}]
-    },
-    {
-      code: '<MyComponent prop=\'bar\'>foo</MyComponent>',
-      options: [{props: 'ignore'}]
-    },
-    {
-      code: '<MyComponent prop=\"bar\">foo</MyComponent>',
-      options: [{props: 'ignore'}]
-    },
-    {
-      code: '<MyComponent prop=\'bar\'>{\'foo\'}</MyComponent>',
-      options: [{children: 'always', props: 'never'}]
-    },
-    {
-      code: '<MyComponent prop={\'bar\'}>foo</MyComponent>',
-      options: [{children: 'never', props: 'always'}]
-    },
-    {
-      code: '<MyComponent prop={\'bar\'}>{\'foo\'}</MyComponent>',
-      options: ['always']
-    },
-    {
-      code: '<MyComponent prop={\"bar\"}>{\"foo\"}</MyComponent>',
-      options: ['always']
-    },
-    {
-      code: '<MyComponent prop={\"bar\"} attr={\'foo\'} />',
-      options: ['always']
-    },
-    {
-      code: '<MyComponent prop=\"bar\" attr=\'foo\' />',
-      options: ['never']
-    },
-    {
-      code: '<MyComponent prop=\'bar\'>foo</MyComponent>',
-      options: ['never']
-    },
-    {
-      code: '<MyComponent prop={`bar ${word} foo`}>{`foo ${word}`}</MyComponent>',
-      options: ['never']
-    }
-  ],
-
-  invalid: [
-    {
-      code: '<App prop={`foo`} />',
-      output: '<App prop="foo" />',
-      options: [{props: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<App prop={\'foo \\u00b7 bar\'}>foo</App>',
-      output: '<App prop=\"foo \\u00b7 bar\">foo</App>',
-      options: [{props: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<App prop={`foo \\n bar`}>foo</App>',
-      output: '<App prop="foo \\n bar">foo</App>',
-      options: [{props: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<App prop={`foo \\u00b7 bar`}>foo</App>',
-      output: '<App prop="foo \\u00b7 bar">foo</App>',
-      options: [{props: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<App prop={`foo \\\'foo\\\' bar`}>foo</App>',
-      output: '<App prop="foo \\\'foo\\\' bar">foo</App>',
-      options: [{props: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<App prop={`foo \\\"foo\\\" bar`}>foo</App>',
-      output: '<App prop="foo \\\"foo\\\" bar">foo</App>',
-      options: [{props: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<App prop={`foo "foo" bar`}>foo</App>',
-      output: '<App prop="foo \\\"foo\\\" bar">foo</App>',
-      options: [{props: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<App prop={`foo`}>foo</App>',
-      output: '<App prop="foo">foo</App>',
-      options: [{props: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<App>{`foo`}</App>',
-      output: '<App>foo</App>',
-      options: [{children: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<App>{`foo "foo" bar`}</App>',
-      output: '<App>foo "foo" bar</App>',
-      options: [{children: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<MyComponent>{\'foo\'}</MyComponent>',
-      output: '<MyComponent>foo</MyComponent>',
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<MyComponent prop={\'bar\'}>foo</MyComponent>',
-      output: '<MyComponent prop=\"bar\">foo</MyComponent>',
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<MyComponent>{\'foo\'}</MyComponent>',
-      output: '<MyComponent>foo</MyComponent>',
-      options: [{children: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<MyComponent prop={\'bar\'}>foo</MyComponent>',
-      output: '<MyComponent prop=\"bar\">foo</MyComponent>',
-      options: [{props: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<MyComponent prop={\"bar \'foo\' \"}>foo</MyComponent>',
-      output: '<MyComponent prop=\"bar \'foo\' \">foo</MyComponent>',
-      options: [{props: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<MyComponent prop={\'bar \"foo\" \'}>foo</MyComponent>',
-      output: '<MyComponent prop=\"bar \\\"foo\\\" \">foo</MyComponent>',
-      options: [{props: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<MyComponent prop=\'bar\'>foo</MyComponent>',
-      output: '<MyComponent prop={\"bar\"}>foo</MyComponent>',
-      options: [{props: 'always'}],
-      errors: [{message: missingCurlyMessage}]
-    },
-    {
-      code: '<MyComponent prop=\"foo \'bar\'\">foo</MyComponent>',
-      output: '<MyComponent prop={\"foo \'bar\'\"}>foo</MyComponent>',
-      options: [{props: 'always'}],
-      errors: [{message: missingCurlyMessage}]
-    },
-    {
-      code: '<MyComponent prop=\'foo "bar"\'>foo</MyComponent>',
-      output: '<MyComponent prop={\"foo \\\"bar\\\"\"}>foo</MyComponent>',
-      options: [{props: 'always'}],
-      errors: [{message: missingCurlyMessage}]
-    },
-    {
-      code: '<MyComponent prop=\"foo \'bar\'\">foo</MyComponent>',
-      output: '<MyComponent prop={\"foo \'bar\'\"}>foo</MyComponent>',
-      options: [{props: 'always'}],
-      errors: [{message: missingCurlyMessage}]
-    },
-    {
-      code: '<MyComponent>foo bar </MyComponent>',
-      output: '<MyComponent>{\"foo bar \"}</MyComponent>',
-      options: [{children: 'always'}],
-      errors: [{message: missingCurlyMessage}]
-    },
-    {
-      code: '<MyComponent>foo bar \'foo\'</MyComponent>',
-      output: '<MyComponent>{\"foo bar \'foo\'\"}</MyComponent>',
-      options: [{children: 'always'}],
-      errors: [{message: missingCurlyMessage}]
-    },
-    {
-      code: '<MyComponent>foo bar \"foo\"</MyComponent>',
-      output: '<MyComponent>{\"foo bar \\\"foo\\\"\"}</MyComponent>',
-      options: [{children: 'always'}],
-      errors: [{message: missingCurlyMessage}]
-    },
-    {
-      code: '<MyComponent>foo bar <App/></MyComponent>',
-      output: '<MyComponent>{\"foo bar \"}<App/></MyComponent>',
-      options: [{children: 'always'}],
-      errors: [{message: missingCurlyMessage}]
-    },
-    {
-      code: '<MyComponent>foo\\nbar</MyComponent>',
-      output: '<MyComponent>{\"foo\\\\nbar\"}</MyComponent>',
-      options: [{children: 'always'}],
-      errors: [{message: missingCurlyMessage}]
-    },
-    {
-      code: '<MyComponent prop={\'bar\'}>{\'foo\'}</MyComponent>',
-      output: '<MyComponent prop=\"bar\">foo</MyComponent>',
-      options: ['never'],
-      errors: [
-        {message: unnecessaryCurlyMessage}, {message: unnecessaryCurlyMessage}
-      ]
-    },
-    {
-      code: '<MyComponent prop=\'bar\'>foo</MyComponent>',
-      output: '<MyComponent prop={\"bar\"}>{\"foo\"}</MyComponent>',
-      options: ['always'],
-      errors: [
-        {message: missingCurlyMessage}, {message: missingCurlyMessage}
-      ]
-    },
-    {
-      code: '<App>{\'foo "bar"\'}</App>',
-      output: '<App>foo \"bar\"</App>',
-      options: [{children: 'never'}],
-      errors: [{message: unnecessaryCurlyMessage}]
-    },
-    {
-      code: '<App>{\"foo \'bar\'\"}</App>',
-      output: '<App>foo \'bar\'</App>',
-      errors: [{message: unnecessaryCurlyMessage}],
-      options: [{children: 'never'}]
-    },
-    {
-      code: '<App prop={\"foo \'bar\' foo \"}>foo</App>',
-      output: '<App prop=\"foo \'bar\' foo \">foo</App>',
-      errors: [{message: unnecessaryCurlyMessage}],
-      options: [{props: 'never'}]
-    },
-    {
-      code: '<App prop={\'foo "bar"\'}>foo</App>',
-      output: '<App prop=\"foo \\\"bar\\\"\">foo</App>',
-      errors: [{message: unnecessaryCurlyMessage}],
-      options: [{props: 'never'}]
-    },
-    {
-      code: '<App prop={\'foo\'} attr={\" foo \"} />',
-      output: '<App prop=\"foo\" attr=\" foo \" />',
-      errors: [
-        {message: unnecessaryCurlyMessage}, {message: unnecessaryCurlyMessage}
-      ],
-      options: [{props: 'never'}]
-    },
-    {
-      code: '<App prop=\'foo\' attr=\"bar\" />',
-      output: '<App prop={\"foo\"} attr={\"bar\"} />',
-      errors: [
-        {message: missingCurlyMessage}, {message: missingCurlyMessage}
-      ],
-      options: [{props: 'always'}]
-    },
-    {
-      code: '<App prop=\'foo\' attr={\"bar\"} />',
-      output: '<App prop={\"foo\"} attr={\"bar\"} />',
-      errors: [{message: missingCurlyMessage}],
-      options: [{props: 'always'}]
-    },
-    {
-      code: '<App prop={\'foo\'} attr=\'bar\' />',
-      output: '<App prop={\'foo\'} attr={\"bar\"} />',
-      errors: [{message: missingCurlyMessage}],
-      options: [{props: 'always'}]
-    }
-  ]
-});
diff --git a/tests/lib/rules/no-access-state-in-setstate.js b/tests/lib/rules/no-access-state-in-setstate.js
new file mode 100644
index 00000000..70f56d23
--- /dev/null
+++ b/tests/lib/rules/no-access-state-in-setstate.js
@@ -0,0 +1,119 @@
+/**
+ * @fileoverview Prevent usage of this.state within setState
+ * @author Rolf Erik Lekang, Jørgen Aaberg
+ */
+'use strict';
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+const rule = require('../../../lib/rules/no-access-state-in-setstate');
+const RuleTester = require('eslint').RuleTester;
+
+const parserOptions = {
+  ecmaVersion: 6,
+  ecmaFeatures: {
+    jsx: true
+  }
+};
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester();
+ruleTester.run('no-access-state-in-setstate', rule, {
+  valid: [{
+    code: [
+      'var Hello = React.createClass({',
+      '  onClick: function() {',
+      '    this.setState(state => ({value: state.value + 1}))',
+      '  }',
+      '});'
+    ].join('\n'),
+    parserOptions: parserOptions
+  }, {
+    code: [
+      'var Hello = React.createClass({',
+      '  multiplyValue: function(obj) {',
+      '    return obj.value*2',
+      '  },',
+      '  onClick: function() {',
+      '    var value = this.state.value',
+      '    this.multiplyValue({ value: value })',
+      '  }',
+      '});'
+    ].join('\n'),
+    parserOptions: parserOptions
+  }],
+
+  invalid: [{
+    code: [
+      'var Hello = React.createClass({',
+      '  onClick: function() {',
+      '    this.setState({value: this.state.value + 1})',
+      '  }',
+      '});'
+    ].join('\n'),
+    parserOptions: parserOptions,
+    errors: [{
+      message: 'Use callback in setState when referencing the previous state.'
+    }]
+  }, {
+    code: [
+      'var Hello = React.createClass({',
+      '  onClick: function() {',
+      '    this.setState(() => ({value: this.state.value + 1}))',
+      '  }',
+      '});'
+    ].join('\n'),
+    parserOptions: parserOptions,
+    errors: [{
+      message: 'Use callback in setState when referencing the previous state.'
+    }]
+  }, {
+    code: [
+      'var Hello = React.createClass({',
+      '  onClick: function() {',
+      '    var nextValue = this.state.value + 1',
+      '    this.setState({value: nextValue})',
+      '  }',
+      '});'
+    ].join('\n'),
+    parserOptions: parserOptions,
+    errors: [{
+      message: 'Use callback in setState when referencing the previous state.'
+    }]
+  }, {
+    code: [
+      'function nextState(state) {',
+      '  return {value: state.value + 1}',
+      '}',
+      'var Hello = React.createClass({',
+      '  onClick: function() {',
+      '    this.setState(nextState(this.state))',
+      '  }',
+      '});'
+    ].join('\n'),
+    parserOptions: parserOptions,
+    errors: [{
+      message: 'Use callback in setState when referencing the previous state.'
+    }]
+  }, {
+    code: [
+      'var Hello = React.createClass({',
+      '  nextState: function() {',
+      '    return {value: this.state.value + 1}',
+      '  },',
+      '  onClick: function() {',
+      '    this.setState(nextState())',
+      '  }',
+      '});'
+    ].join('\n'),
+    parserOptions: parserOptions,
+    errors: [{
+      message: 'Use callback in setState when referencing the previous state.'
+    }]
+  }]
+});
diff --git a/tests/lib/rules/no-direct-mutation-state.js b/tests/lib/rules/no-direct-mutation-state.js
index b1e78899..6886125c 100644
--- a/tests/lib/rules/no-direct-mutation-state.js
+++ b/tests/lib/rules/no-direct-mutation-state.js
@@ -69,28 +69,6 @@ ruleTester.run('no-direct-mutation-state', rule, {
       '  }',
       '}'
     ].join('\n')
-  }, {
-    code: [
-      'class Hello extends React.Component {',
-      '  constructor() {',
-      '    this.state.foo = 1;',
-      '  }',
-      '}'
-    ].join('\n')
-  }, {
-    code: `
-      class OneComponent extends Component {
-        constructor() {
-          super();
-          class AnotherComponent extends Component {
-            constructor() {
-              super();
-            }
-          }
-          this.state = {};
-        }
-      }
-    `
   }],
 
   invalid: [{
@@ -105,18 +83,6 @@ ruleTester.run('no-direct-mutation-state', rule, {
     errors: [{
       message: 'Do not mutate state directly. Use setState().'
     }]
-  }, {
-    code: [
-      'var Hello = createReactClass({',
-      '  render: function() {',
-      '    this.state.foo++;',
-      '    return <div>Hello {this.props.name}</div>;',
-      '  }',
-      '});'
-    ].join('\n'),
-    errors: [{
-      message: 'Do not mutate state directly. Use setState().'
-    }]
   }, {
     code: [
       'var Hello = createReactClass({',
diff --git a/tests/lib/rules/no-typos.js b/tests/lib/rules/no-typos.js
index f5374505..1e0efa87 100644
--- a/tests/lib/rules/no-typos.js
+++ b/tests/lib/rules/no-typos.js
@@ -26,6 +26,7 @@ const ERROR_MESSAGE_LIFECYCLE_METHOD = 'Typo in component lifecycle method decla
 
 const ruleTester = new RuleTester();
 ruleTester.run('no-typos', rule, {
+
   valid: [{
     code: [
       'class First {',
@@ -37,7 +38,8 @@ ruleTester.run('no-typos', rule, {
     ].join('\n'),
     parser: 'babel-eslint',
     parserOptions: parserOptions
-  }, {
+  },
+  {
     code: [
       'class First {}',
       'First.PropTypes = {key: "myValue"};',
@@ -238,112 +240,6 @@ ruleTester.run('no-typos', rule, {
       '}'
     ].join('\n'),
     parserOptions: parserOptions
-  }, {
-    // PropTypes declared on a component that is detected through JSDoc comments and is
-    // declared AFTER the PropTypes assignment does not work.
-    code: `
-      MyComponent.PROPTYPES = {}
-      /** @extends React.Component */
-      class MyComponent extends BaseComponent {}
-    `,
-    parserOptions: parserOptions
-  }, {
-    // https://github.com/yannickcr/eslint-plugin-react/issues/1353
-    code: `
-      function test(b) {
-        return a.bind(b);
-      }
-      function a() {}
-    `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions
-  }, {
-    code: `class Component extends React.Component {};
-     Component.propTypes = {
-       a: PropTypes.number.isRequired
-     }
-   `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions
-  }, {
-    code: `class Component extends React.Component {};
-     Component.propTypes = {
-       e: PropTypes.shape({
-         ea: PropTypes.string,
-       })
-     }
-   `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions
-  }, {
-    code: `class Component extends React.Component {};
-     Component.propTypes = {
-       a: PropTypes.string,
-       b: PropTypes.string.isRequired,
-       c: PropTypes.shape({
-         d: PropTypes.string,
-         e: PropTypes.number.isRequired,
-       }).isRequired
-     }
-   `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions
-  }, {
-    code: `class Component extends React.Component {};
-    Component.propTypes = {
-       a: PropTypes.oneOfType([
-         PropTypes.string,
-         PropTypes.number
-       ])
-     }
-   `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions
-  }, {
-    code: `class Component extends React.Component {};
-    Component.propTypes = {
-       a: PropTypes.oneOf([
-         'hello',
-         'hi'
-       ])
-     }
-   `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions
-  }, {
-    code: `class Component extends React.Component {};
-     Component.childContextTypes = {
-       a: PropTypes.string,
-       b: PropTypes.string.isRequired,
-       c: PropTypes.shape({
-         d: PropTypes.string,
-         e: PropTypes.number.isRequired,
-       }).isRequired
-     }
-   `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions
-  }, {
-    code: `class Component extends React.Component {};
-     Component.contextTypes = {
-       a: PropTypes.string,
-       b: PropTypes.string.isRequired,
-       c: PropTypes.shape({
-         d: PropTypes.string,
-         e: PropTypes.number.isRequired,
-       }).isRequired
-     }
-   `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions
-  }, {
-    code: `
-      const fn = (err, res) => {
-        const { body: data = {} } = { ...res };
-        data.time = data.time || {};
-      };
-    `,
-    parser: 'babel-eslint'
   }],
 
   invalid: [{
@@ -530,21 +426,6 @@ ruleTester.run('no-typos', rule, {
     ].join('\n'),
     parserOptions: parserOptions,
     errors: [{message: ERROR_MESSAGE}]
-  }, {
-    code: [
-      'Component.defaultprops = {}',
-      'class Component extends React.Component {}'
-    ].join('\n'),
-    parserOptions: parserOptions,
-    errors: [{message: ERROR_MESSAGE}]
-  }, {
-    code: `
-      /** @extends React.Component */
-      class MyComponent extends BaseComponent {}
-      MyComponent.PROPTYPES = {}
-    `,
-    parserOptions: parserOptions,
-    errors: [{message: ERROR_MESSAGE}]
   }, {
     code: [
       'class Hello extends React.Component {',
@@ -662,106 +543,5 @@ ruleTester.run('no-typos', rule, {
       message: ERROR_MESSAGE_LIFECYCLE_METHOD,
       type: 'MethodDefinition'
     }]
-  }, {
-    code: `class Component extends React.Component {};
-     Component.propTypes = {
-        a: PropTypes.Number.isRequired
-     }
-   `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions,
-    errors: [{
-      message: 'Typo in declared prop type: Number'
-    }]
-  }, {
-    code: `class Component extends React.Component {};
-     Component.propTypes = {
-        a: PropTypes.number.isrequired
-     }
-   `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions,
-    errors: [{
-      message: 'Typo in prop type chain qualifier: isrequired'
-    }]
-  }, {
-    code: `class Component extends React.Component {};
-     Component.propTypes = {
-        a: PropTypes.Number
-     }
-   `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions,
-    errors: [{
-      message: 'Typo in declared prop type: Number'
-    }]
-  }, {
-    code: `class Component extends React.Component {};
-    Component.propTypes = {
-       a: PropTypes.shape({
-         b: PropTypes.String,
-         c: PropTypes.number.isRequired,
-       })
-    }
-   `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions,
-    errors: [{
-      message: 'Typo in declared prop type: String'
-    }]
-  }, {
-    code: `class Component extends React.Component {};
-    Component.propTypes = {
-       a: PropTypes.oneOfType([
-         PropTypes.bools,
-         PropTypes.number,
-       ])
-     }
-   `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions,
-    errors: [{
-      message: 'Typo in declared prop type: bools'
-    }]
-  }, {
-    code: `class Component extends React.Component {};
-      Component.propTypes = {
-        a: PropTypes.bools,
-        b: PropTypes.Array,
-        c: PropTypes.function,
-        d: PropTypes.objectof,
-      }
-    `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions,
-    errors: [{
-      message: 'Typo in declared prop type: bools'
-    }, {
-      message: 'Typo in declared prop type: Array'
-    }, {
-      message: 'Typo in declared prop type: function'
-    }, {
-      message: 'Typo in declared prop type: objectof'
-    }]
-  }, {
-    code: `class Component extends React.Component {};
-      Component.childContextTypes = {
-        a: PropTypes.bools,
-        b: PropTypes.Array,
-        c: PropTypes.function,
-        d: PropTypes.objectof,
-      }
-    `,
-    parser: 'babel-eslint',
-    parserOptions: parserOptions,
-    errors: [{
-      message: 'Typo in declared prop type: bools'
-    }, {
-      message: 'Typo in declared prop type: Array'
-    }, {
-      message: 'Typo in declared prop type: function'
-    }, {
-      message: 'Typo in declared prop type: objectof'
-    }]
   }]
 });
diff --git a/tests/lib/rules/no-unused-prop-types.js b/tests/lib/rules/no-unused-prop-types.js
index 62ef6094..d14ec946 100644
--- a/tests/lib/rules/no-unused-prop-types.js
+++ b/tests/lib/rules/no-unused-prop-types.js
@@ -824,87 +824,6 @@ ruleTester.run('no-unused-prop-types', rule, {
         '}'
       ].join('\n'),
       parser: 'babel-eslint'
-    }, {
-      code: `
-      type PropsA = { a: string }
-      type PropsB = { b: string }
-      type Props = PropsA & PropsB;
-      
-      class MyComponent extends React.Component {
-        props: Props;
-        
-        render() {
-          return <div>{this.props.a} - {this.props.b}</div>
-        }
-      }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type PropsA = { foo: string };
-        type PropsB = { bar: string };
-        type PropsC = { zap: string };
-        type Props = PropsA & PropsB;
-
-        class Bar extends React.Component {
-          props: Props & PropsC;
-          
-          render() {
-            return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        import type { PropsA } from "./myPropsA";
-        type PropsB = { bar: string };
-        type PropsC = { zap: string };
-        type Props = PropsA & PropsB;
-
-        class Bar extends React.Component {
-          props: Props & PropsC;
-          
-          render() {
-            return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type PropsB = { foo: string };
-        type PropsC = { bar: string };
-        type Props = PropsB & {
-          zap: string 
-        };
-
-        class Bar extends React.Component {
-          props: Props & PropsC;
-          
-          render() {
-            return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type PropsB = { foo: string };
-        type PropsC = { bar: string };
-        type Props = {
-          zap: string 
-        } & PropsB;
-
-        class Bar extends React.Component {
-          props: Props & PropsC;
-          
-          render() {
-            return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
     }, {
       code: [
         'import type Props from "fake";',
@@ -2110,104 +2029,6 @@ ruleTester.run('no-unused-prop-types', rule, {
       ].join('\n'),
       parser: 'babel-eslint',
       options: [{skipShapeProps: false}]
-    }, {
-      // issue #106
-      code: `
-        import React from 'react';
-        import SharedPropTypes from './SharedPropTypes';
-
-        export default class A extends React.Component {
-          render() {
-            return (
-              <span
-                a={this.props.a}
-                b={this.props.b}
-                c={this.props.c}>
-                {this.props.children}
-              </span>
-            );
-          }
-        }
-
-        A.propTypes = {
-          a: React.PropTypes.string,
-          ...SharedPropTypes // eslint-disable-line object-shorthand
-        };
-      `,
-      parser: 'babel-eslint'
-    }, {
-      // issue #933
-      code: `
-        type Props = {
-          +foo: number
-        }
-        class MyComponent extends React.Component {
-          render() {
-            return <div>{this.props.foo}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Props = {
-          \'completed?\': boolean,
-        };
-        const Hello = (props: Props): React.Element => {
-          return <div>{props[\'completed?\']}</div>;
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Person = {
-          firstname: string
-        }
-        class MyComponent extends React.Component<void, Props, void> {
-          render() {
-            return <div>Hello {this.props.firstname}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Person = {
-          firstname: string
-        }
-        class MyComponent extends React.Component<void, Props, void> {
-          render() {
-            return <div>Hello {this.props.firstname}</div>
-          }
-        }
-      `,
-      settings: {react: {flowVersion: '0.52'}},
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Person = {
-          firstname: string
-        }
-        class MyComponent extends React.Component<Props> {
-          render() {
-            return <div>Hello {this.props.firstname}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Person = {
-          firstname: string
-        }
-        class MyComponent extends React.Component<Props> {
-          render() {
-            return <div>Hello {this.props.firstname}</div>
-          }
-        }
-      `,
-      settings: {react: {flowVersion: '0.53'}},
-      parser: 'babel-eslint'
     }
   ],
 
@@ -2791,83 +2612,6 @@ ruleTester.run('no-unused-prop-types', rule, {
       errors: [
         {message: '\'unused\' PropType is defined but prop is never used'}
       ]
-    }, {
-      code: `
-      type PropsA = { a: string }
-      type PropsB = { b: string }
-      type Props = PropsA & PropsB;
-      
-      class MyComponent extends React.Component {
-        props: Props;
-        
-        render() {
-          return <div>{this.props.a}</div>
-        }
-      }
-      `,
-      parser: 'babel-eslint',
-      errors: [
-        {message: '\'b\' PropType is defined but prop is never used'}
-      ]
-    }, {
-      code: `
-        type PropsA = { foo: string };
-        type PropsB = { bar: string };
-        type PropsC = { zap: string };
-        type Props = PropsA & PropsB;
-
-        class Bar extends React.Component {
-          props: Props & PropsC;
-          
-          render() {
-            return <div>{this.props.foo} - {this.props.bar}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint',
-      errors: [
-        {message: '\'zap\' PropType is defined but prop is never used'}
-      ]
-    }, {
-      code: `
-        type PropsB = { foo: string };
-        type PropsC = { bar: string };
-        type Props = PropsB & {
-          zap: string 
-        };
-
-        class Bar extends React.Component {
-          props: Props & PropsC;
-          
-          render() {
-            return <div>{this.props.foo} - {this.props.bar}</div>
-          }
-        }
-      `,
-      errors: [
-        {message: '\'zap\' PropType is defined but prop is never used'}
-      ],
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type PropsB = { foo: string };
-        type PropsC = { bar: string };
-        type Props = {
-          zap: string 
-        } & PropsB;
-
-        class Bar extends React.Component {
-          props: Props & PropsC;
-          
-          render() {
-            return <div>{this.props.foo} - {this.props.bar}</div>
-          }
-        }
-      `,
-      errors: [
-        {message: '\'zap\' PropType is defined but prop is never used'}
-      ],
-      parser: 'babel-eslint'
     }, {
       code: [
         'class Hello extends React.Component {',
@@ -3667,72 +3411,6 @@ ruleTester.run('no-unused-prop-types', rule, {
       errors: [{
         message: '\'aProp\' PropType is defined but prop is never used'
       }]
-    }, {
-      code: `
-        type Props = {
-          firstname: string,
-          lastname: string,
-        }
-        class MyComponent extends React.Component<void, Props, void> {
-          render() {
-            return <div>Hello {this.props.firstname}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint',
-      errors: [{
-        message: '\'lastname\' PropType is defined but prop is never used'
-      }]
-    }, {
-      code: `
-        type Props = {
-          firstname: string,
-          lastname: string,
-        }
-        class MyComponent extends React.Component<void, Props, void> {
-          render() {
-            return <div>Hello {this.props.firstname}</div>
-          }
-        }
-      `,
-      settings: {react: {flowVersion: '0.52'}},
-      parser: 'babel-eslint',
-      errors: [{
-        message: '\'lastname\' PropType is defined but prop is never used'
-      }]
-    }, {
-      code: `
-        type Props = {
-          firstname: string,
-          lastname: string,
-        }
-        class MyComponent extends React.Component<Props> {
-          render() {
-            return <div>Hello {this.props.firstname}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint',
-      errors: [{
-        message: '\'lastname\' PropType is defined but prop is never used'
-      }]
-    }, {
-      code: `
-        type Props = {
-          firstname: string,
-          lastname: string,
-        }
-        class MyComponent extends React.Component<Props> {
-          render() {
-            return <div>Hello {this.props.firstname}</div>
-          }
-        }
-      `,
-      settings: {react: {flowVersion: '0.53'}},
-      parser: 'babel-eslint',
-      errors: [{
-        message: '\'lastname\' PropType is defined but prop is never used'
-      }]
     }
 
     /* , {
diff --git a/tests/lib/rules/no-unused-state.js b/tests/lib/rules/no-unused-state.js
index 4fbb8a4f..c5e60d89 100644
--- a/tests/lib/rules/no-unused-state.js
+++ b/tests/lib/rules/no-unused-state.js
@@ -46,70 +46,6 @@ eslintTester.run('no-unused-state', rule, {
         return <SomeComponent foo={this.state.foo} />;
       }
     });`,
-    `var ComputedKeyFromVariableTest = createReactClass({
-      getInitialState: function() {
-        return { [foo]: 0 };
-      },
-      render: function() {
-        return <SomeComponent />;
-      }
-    });`,
-    `var ComputedKeyFromBooleanLiteralTest = createReactClass({
-      getInitialState: function() {
-        return { [true]: 0 };
-      },
-      render: function() {
-        return <SomeComponent foo={this.state[true]} />;
-      }
-    });`,
-    `var ComputedKeyFromNumberLiteralTest = createReactClass({
-      getInitialState: function() {
-        return { [123]: 0 };
-      },
-      render: function() {
-        return <SomeComponent foo={this.state[123]} />;
-      }
-    });`,
-    `var ComputedKeyFromExpressionTest = createReactClass({
-      getInitialState: function() {
-        return { [foo + bar]: 0 };
-      },
-      render: function() {
-        return <SomeComponent />;
-      }
-    });`,
-    `var ComputedKeyFromBinaryExpressionTest = createReactClass({
-      getInitialState: function() {
-        return { ['foo' + 'bar' * 8]: 0 };
-      },
-      render: function() {
-        return <SomeComponent />;
-      }
-    });`,
-    `var ComputedKeyFromStringLiteralTest = createReactClass({
-      getInitialState: function() {
-        return { ['foo']: 0 };
-      },
-      render: function() {
-        return <SomeComponent foo={this.state.foo} />;
-      }
-    });`,
-    `var ComputedKeyFromTemplateLiteralTest = createReactClass({
-      getInitialState: function() {
-        return { [\`foo\${bar}\`]: 0 };
-      },
-      render: function() {
-        return <SomeComponent />;
-      }
-    });`,
-    `var ComputedKeyFromTemplateLiteralTest = createReactClass({
-      getInitialState: function() {
-        return { [\`foo\`]: 0 };
-      },
-      render: function() {
-        return <SomeComponent foo={this.state['foo']} />;
-      }
-    });`,
     `var GetInitialStateMethodTest = createReactClass({
       getInitialState() {
         return { foo: 0 };
@@ -150,70 +86,6 @@ eslintTester.run('no-unused-state', rule, {
         return <SomeComponent foo={this.state.foo} />;
       }
     }`,
-    `class ComputedKeyFromVariableTest extends React.Component {
-      constructor() {
-        this.state = { [foo]: 0 };
-      }
-      render() {
-        return <SomeComponent />;
-      }
-    }`,
-    `class ComputedKeyFromBooleanLiteralTest extends React.Component {
-      constructor() {
-        this.state = { [false]: 0 };
-      }
-      render() {
-        return <SomeComponent foo={this.state['false']} />;
-      }
-    }`,
-    `class ComputedKeyFromNumberLiteralTest extends React.Component {
-      constructor() {
-        this.state = { [345]: 0 };
-      }
-      render() {
-        return <SomeComponent foo={this.state[345]} />;
-      }
-    }`,
-    `class ComputedKeyFromExpressionTest extends React.Component {
-      constructor() {
-        this.state = { [foo + bar]: 0 };
-      }
-      render() {
-        return <SomeComponent />;
-      }
-    }`,
-    `class ComputedKeyFromBinaryExpressionTest extends React.Component {
-      constructor() {
-        this.state = { [1 + 2 * 8]: 0 };
-      }
-      render() {
-        return <SomeComponent />;
-      }
-    }`,
-    `class ComputedKeyFromStringLiteralTest extends React.Component {
-      constructor() {
-        this.state = { ['foo']: 0 };
-      }
-      render() {
-        return <SomeComponent foo={this.state.foo} />;
-      }
-    }`,
-    `class ComputedKeyFromTemplateLiteralTest extends React.Component {
-      constructor() {
-        this.state = { [\`foo\${bar}\`]: 0 };
-      }
-      render() {
-        return <SomeComponent />;
-      }
-    }`,
-    `class ComputedKeyFromTemplateLiteralTest extends React.Component {
-      constructor() {
-        this.state = { [\`foo\`]: 0 };
-      }
-      render() {
-        return <SomeComponent foo={this.state.foo} />;
-      }
-    }`,
     `class SetStateTest extends React.Component {
         onFooChange(newFoo) {
           this.setState({ foo: newFoo });
@@ -412,50 +284,6 @@ eslintTester.run('no-unused-state', rule, {
         })`,
       errors: getErrorMessages(['foo'])
     },
-    {
-      code: `var UnusedComputedStringLiteralKeyStateTest = createReactClass({
-          getInitialState: function() {
-            return { ['foo']: 0 };
-          },
-          render: function() {
-            return <SomeComponent />;
-          }
-        })`,
-      errors: getErrorMessages(['foo'])
-    },
-    {
-      code: `var UnusedComputedTemplateLiteralKeyStateTest = createReactClass({
-          getInitialState: function() {
-            return { [\`foo\`]: 0 };
-          },
-          render: function() {
-            return <SomeComponent />;
-          }
-        })`,
-      errors: getErrorMessages(['foo'])
-    },
-    {
-      code: `var UnusedComputedNumberLiteralKeyStateTest = createReactClass({
-          getInitialState: function() {
-            return { [123]: 0 };
-          },
-          render: function() {
-            return <SomeComponent />;
-          }
-        })`,
-      errors: getErrorMessages(['123'])
-    },
-    {
-      code: `var UnusedComputedBooleanLiteralKeyStateTest = createReactClass({
-          getInitialState: function() {
-            return { [true]: 0 };
-          },
-          render: function() {
-            return <SomeComponent />;
-          }
-        })`,
-      errors: getErrorMessages(['true'])
-    },
     {
       code: `var UnusedGetInitialStateMethodTest = createReactClass({
           getInitialState() {
@@ -510,66 +338,6 @@ eslintTester.run('no-unused-state', rule, {
       errors: getErrorMessages(['foo']),
       parser: 'babel-eslint'
     },
-    {
-      code: `class UnusedComputedStringLiteralKeyStateTest extends React.Component {
-          state = { ['foo']: 0 };
-          render() {
-            return <SomeComponent />;
-          }
-        }`,
-      errors: getErrorMessages(['foo']),
-      parser: 'babel-eslint'
-    },
-    {
-      code: `class UnusedComputedTemplateLiteralKeyStateTest extends React.Component {
-          state = { [\`foo\`]: 0 };
-          render() {
-            return <SomeComponent />;
-          }
-        }`,
-      errors: getErrorMessages(['foo']),
-      parser: 'babel-eslint'
-    },
-    {
-      code: `class UnusedComputedTemplateLiteralKeyStateTest extends React.Component {
-          state = { [\`foo \\n bar\`]: 0 };
-          render() {
-            return <SomeComponent />;
-          }
-        }`,
-      errors: getErrorMessages(['foo \\n bar']),
-      parser: 'babel-eslint'
-    },
-    {
-      code: `class UnusedComputedBooleanLiteralKeyStateTest extends React.Component {
-          state = { [true]: 0 };
-          render() {
-            return <SomeComponent />;
-          }
-        }`,
-      errors: getErrorMessages(['true']),
-      parser: 'babel-eslint'
-    },
-    {
-      code: `class UnusedComputedNumberLiteralKeyStateTest extends React.Component {
-          state = { [123]: 0 };
-          render() {
-            return <SomeComponent />;
-          }
-        }`,
-      errors: getErrorMessages(['123']),
-      parser: 'babel-eslint'
-    },
-    {
-      code: `class UnusedComputedFloatLiteralKeyStateTest extends React.Component {
-          state = { [123.12]: 0 };
-          render() {
-            return <SomeComponent />;
-          }
-        }`,
-      errors: getErrorMessages(['123.12']),
-      parser: 'babel-eslint'
-    },
     {
       code: `class UnusedStateWhenPropsAreSpreadTest extends React.Component {
           constructor() {
diff --git a/tests/lib/rules/prop-types.js b/tests/lib/rules/prop-types.js
index 9bc4223e..bc6ec6fe 100644
--- a/tests/lib/rules/prop-types.js
+++ b/tests/lib/rules/prop-types.js
@@ -1487,19 +1487,6 @@ ruleTester.run('prop-types', rule, {
         '}'
       ].join('\n'),
       parser: 'babel-eslint'
-    }, {
-      code: [
-        'type Person = {',
-        '  firstname: string',
-        '};',
-        'class Hello extends React.Component<void, Person, void> {',
-        '  render () {',
-        '    return <div>Hello {this.props.firstname}</div>;',
-        '  }',
-        '}'
-      ].join('\n'),
-      settings: {react: {flowVersion: '0.52'}},
-      parser: 'babel-eslint'
     }, {
       code: [
         'type Person = {',
@@ -1520,12 +1507,13 @@ ruleTester.run('prop-types', rule, {
         '};',
         'class Hello extends React.Component<void, Person, void> {',
         '  render () {',
-        '    const { firstname } = this.props;',
+        '    const {',
+        '      firstname,',
+        '    } = this.props;',
         '    return <div>Hello {firstname}</div>;',
         '  }',
         '}'
       ].join('\n'),
-      settings: {react: {flowVersion: '0.52'}},
       parser: 'babel-eslint'
     }, {
       code: [
@@ -1537,17 +1525,6 @@ ruleTester.run('prop-types', rule, {
         '}'
       ].join('\n'),
       parser: 'babel-eslint'
-    }, {
-      code: [
-        'type Props = {name: {firstname: string;};};',
-        'class Hello extends React.Component<void, Props, void> {',
-        '  render () {',
-        '    return <div>Hello {this.props.name.firstname}</div>;',
-        '  }',
-        '}'
-      ].join('\n'),
-      settings: {react: {flowVersion: '0.52'}},
-      parser: 'babel-eslint'
     }, {
       code: [
         'import type Props from "fake";',
@@ -1558,17 +1535,6 @@ ruleTester.run('prop-types', rule, {
         '}'
       ].join('\n'),
       parser: 'babel-eslint'
-    }, {
-      code: [
-        'import type Props from "fake";',
-        'class Hello extends React.Component<void, Props, void> {',
-        '  render () {',
-        '    return <div>Hello {this.props.firstname}</div>;',
-        '  }',
-        '}'
-      ].join('\n'),
-      settings: {react: {flowVersion: '0.52'}},
-      parser: 'babel-eslint'
     }, {
       code: [
         'type Person = {',
@@ -1581,29 +1547,6 @@ ruleTester.run('prop-types', rule, {
         '}'
       ].join('\n'),
       parser: 'babel-eslint'
-    }, {
-      code: [
-        'type Person = {',
-        '  firstname: string',
-        '};',
-        'class Hello extends React.Component<void, { person: Person }, void> {',
-        '  render () {',
-        '    return <div>Hello {this.props.person.firstname}</div>;',
-        '  }',
-        '}'
-      ].join('\n'),
-      settings: {react: {flowVersion: '0.52'}},
-      parser: 'babel-eslint'
-    }, {
-      code: [
-        'type Props = {result?: {ok?: ?string | boolean;}|{ok?: ?number | Array}};',
-        'class Hello extends React.Component<void, Props, void> {',
-        '  render () {',
-        '    return <div>Hello {this.props.result.ok}</div>;',
-        '  }',
-        '}'
-      ].join('\n'),
-      parser: 'babel-eslint'
     }, {
       code: [
         'type Props = {result?: {ok?: ?string | boolean;}|{ok?: ?number | Array}};',
@@ -1613,218 +1556,6 @@ ruleTester.run('prop-types', rule, {
         '  }',
         '}'
       ].join('\n'),
-      settings: {react: {flowVersion: '0.52'}},
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Props = {
-          foo: string,
-        };
-
-        class Bar extends React.Component<Props> {
-          render() {
-            return <div>{this.props.foo}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Props = {
-          foo: string,
-        };
-
-        class Bar extends React.Component<Props> {
-          render() {
-            return <div>{this.props.foo}</div>
-          }
-        }
-      `,
-      settings: {react: {flowVersion: '0.53'}},
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type FancyProps = {
-          foo: string,
-        };
-
-        class Bar extends React.Component<FancyProps> {
-          render() {
-            return <div>{this.props.foo}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type FancyProps = {
-          foo: string,
-        };
-
-        class Bar extends React.Component<FancyProps> {
-          render() {
-            return <div>{this.props.foo}</div>
-          }
-        }
-      `,
-      settings: {react: {flowVersion: '0.53'}},
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type PropsA = { foo: string };
-        type PropsB = { bar: string };
-        type Props = PropsA & PropsB;
-
-        class Bar extends React.Component {
-          props: Props;
-          
-          render() {
-            return <div>{this.props.foo} - {this.props.bar}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type PropsA = { foo: string };
-        type PropsB = { bar: string };
-        type PropsC = { zap: string };
-        type Props = PropsA & PropsB;
-
-        class Bar extends React.Component {
-          props: Props & PropsC;
-          
-          render() {
-            return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        import type { PropsA } from "./myPropsA";
-        type PropsB = { bar: string };
-        type PropsC = { zap: string };
-        type Props = PropsA & PropsB;
-
-        class Bar extends React.Component {
-          props: Props & PropsC;
-          
-          render() {
-            return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type PropsA = { bar: string };
-        type PropsB = { zap: string };
-        type Props = PropsA & {
-          baz: string 
-        };
-
-        class Bar extends React.Component {
-          props: Props & PropsB;
-          
-          render() {
-            return <div>{this.props.bar} - {this.props.zap} - {this.props.baz}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type PropsA = { bar: string };
-        type PropsB = { zap: string };
-        type Props =  {
-          baz: string 
-        } & PropsA;
-
-        class Bar extends React.Component {
-          props: Props & PropsB;
-          
-          render() {
-            return <div>{this.props.bar} - {this.props.zap} - {this.props.baz}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Props = { foo: string }
-        function higherOrderComponent<Props>() {
-          return class extends React.Component<Props> {
-            render() {
-              return <div>{this.props.foo}</div>
-            }
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        function higherOrderComponent<P: { foo: string }>() {
-          return class extends React.Component<P> {
-            render() {
-              return <div>{this.props.foo}</div>
-            }
-          }
-        }
-      `,
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        const withOverlayState = <P: {foo: string}>(WrappedComponent: ComponentType<P>): CpmponentType<P> => (
-          class extends React.Component<P> {
-            constructor(props) {
-              super(props);
-              this.state = {foo: props.foo}
-            }
-            render() {
-              return <div>Hello World</div>
-            }
-          }
-        )
-      `,
-      parser: 'babel-eslint'
-    },
-
-    // issue #1288
-    `function Foo() {
-      const props = {}
-      props.bar = 'bar'
-      return <div {...props} />
-    }`,
-    // issue #1288
-    `function Foo(props) {
-      props.bar = 'bar';
-      return <div {...props} />;
-    }`,
-    {
-      // issue #106
-      code: `
-      import React from 'react';
-      import SharedPropTypes from './SharedPropTypes';
-
-      export default class A extends React.Component {
-        render() {
-          return (
-            <span
-              a={this.props.a}
-              b={this.props.b}
-              c={this.props.c}>
-              {this.props.children}
-            </span>
-          );
-        }
-      }
-
-      A.propTypes = {
-        a: React.PropTypes.string,
-        ...SharedPropTypes // eslint-disable-line object-shorthand
-      };
-    `,
       parser: 'babel-eslint'
     }
   ],
@@ -2497,26 +2228,6 @@ ruleTester.run('prop-types', rule, {
       errors: [
         {message: '\'lastname\' is missing in props validation'}
       ]
-    }, {
-      code: [
-        'class Test extends Foo.Component {',
-        '  render() {',
-        '    return (',
-        '      <div>{this.props.firstname} {this.props.lastname}</div>',
-        '    );',
-        '  }',
-        '}',
-        'Test.propTypes = Object.freeze({',
-        '  firstname: PropTypes.string',
-        '});'
-      ].join('\n'),
-      parser: 'babel-eslint',
-      settings: Object.assign({}, settings, {
-        propWrapperFunctions: ['Object.freeze']
-      }),
-      errors: [
-        {message: '\'lastname\' is missing in props validation'}
-      ]
     }, {
       code: [
         '/** @jsx Foo */',
@@ -3103,36 +2814,15 @@ ruleTester.run('prop-types', rule, {
         '};',
         'class Hello extends React.Component<void, Person, void> {',
         '  render () {',
-        '    return <div>Hello {this.props.lastname}</div>;',
-        '  }',
-        '}'
-      ].join('\n'),
-      settings: {react: {flowVersion: '0.52'}},
-      errors: [{
-        message: '\'lastname\' is missing in props validation',
-        line: 6,
-        column: 35,
-        type: 'Identifier'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: [
-        'type Person = {',
-        '  firstname: string',
-        '};',
-        'class Hello extends React.Component<void, Person, void> {',
-        '  render () {',
-        '    const {',
-        '      lastname,',
-        '    } = this.props;',
+        '    const { lastname } = this.props;',
         '    return <div>Hello {lastname}</div>;',
         '  }',
         '}'
       ].join('\n'),
       errors: [{
         message: '\'lastname\' is missing in props validation',
-        line: 7,
-        column: 7,
+        line: 6,
+        column: 13,
         type: 'Property'
       }],
       parser: 'babel-eslint'
@@ -3150,7 +2840,6 @@ ruleTester.run('prop-types', rule, {
         '  }',
         '}'
       ].join('\n'),
-      settings: {react: {flowVersion: '0.52'}},
       errors: [{
         message: '\'lastname\' is missing in props validation',
         line: 7,
@@ -3174,39 +2863,6 @@ ruleTester.run('prop-types', rule, {
         type: 'Identifier'
       }],
       parser: 'babel-eslint'
-    }, {
-      code: [
-        'type Props = {name: {firstname: string;};};',
-        'class Hello extends React.Component<void, Props, void> {',
-        '  render () {',
-        '    return <div>Hello {this.props.name.lastname}</div>;',
-        '  }',
-        '}'
-      ].join('\n'),
-      settings: {react: {flowVersion: '0.52'}},
-      errors: [{
-        message: '\'name.lastname\' is missing in props validation',
-        line: 4,
-        column: 40,
-        type: 'Identifier'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: [
-        'type Props = {result?: {ok: string | boolean;}|{ok: number | Array}};',
-        'class Hello extends React.Component<void, Props, void> {',
-        '  render () {',
-        '    return <div>Hello {this.props.result.notok}</div>;',
-        '  }',
-        '}'
-      ].join('\n'),
-      errors: [{
-        message: '\'result.notok\' is missing in props validation',
-        line: 4,
-        column: 42,
-        type: 'Identifier'
-      }],
-      parser: 'babel-eslint'
     }, {
       code: [
         'type Props = {result?: {ok: string | boolean;}|{ok: number | Array}};',
@@ -3216,7 +2872,6 @@ ruleTester.run('prop-types', rule, {
         '  }',
         '}'
       ].join('\n'),
-      settings: {react: {flowVersion: '0.52'}},
       errors: [{
         message: '\'result.notok\' is missing in props validation',
         line: 4,
@@ -3242,264 +2897,6 @@ ruleTester.run('prop-types', rule, {
         type: 'Identifier'
       }],
       parser: 'babel-eslint'
-    }, {
-      code: [
-        'type Person = {',
-        '  firstname: string',
-        '};',
-        'class Hello extends React.Component<void, { person: Person }, void> {',
-        '  render () {',
-        '    return <div>Hello {this.props.person.lastname}</div>;',
-        '  }',
-        '}'
-      ].join('\n'),
-      settings: {react: {flowVersion: '0.52'}},
-      errors: [{
-        message: '\'person.lastname\' is missing in props validation',
-        line: 6,
-        column: 42,
-        type: 'Identifier'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Props = {
-          foo: string,
-        };
-
-        class Bar extends React.Component<Props> {
-          render() {
-            return <div>{this.props.bar}</div>
-          }
-        }
-      `,
-      errors: [{
-        message: '\'bar\' is missing in props validation',
-        line: 8,
-        column: 37,
-        type: 'Identifier'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Props = {
-          foo: string,
-        };
-
-        class Bar extends React.Component<Props> {
-          render() {
-            return <div>{this.props.bar}</div>
-          }
-        }
-      `,
-      settings: {react: {flowVersion: '0.53'}},
-      errors: [{
-        message: '\'bar\' is missing in props validation',
-        line: 8,
-        column: 37,
-        type: 'Identifier'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type FancyProps = {
-          foo: string,
-        };
-
-        class Bar extends React.Component<FancyProps> {
-          render() {
-            return <div>{this.props.bar}</div>
-          }
-        }
-      `,
-      errors: [{
-        message: '\'bar\' is missing in props validation',
-        line: 8,
-        column: 37,
-        type: 'Identifier'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type FancyProps = {
-          foo: string,
-        };
-
-        class Bar extends React.Component<FancyProps> {
-          render() {
-            return <div>{this.props.bar}</div>
-          }
-        }
-      `,
-      settings: {react: {flowVersion: '0.53'}},
-      errors: [{
-        message: '\'bar\' is missing in props validation',
-        line: 8,
-        column: 37,
-        type: 'Identifier'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Person = {
-          firstname: string
-        };
-        class Hello extends React.Component<{ person: Person }> {
-          render () {
-            return <div>Hello {this.props.person.lastname}</div>;
-          }
-        }
-      `,
-      errors: [{
-        message: '\'person.lastname\' is missing in props validation',
-        line: 7,
-        column: 50,
-        type: 'Identifier'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Person = {
-          firstname: string
-        };
-        class Hello extends React.Component<{ person: Person }> {
-          render () {
-            return <div>Hello {this.props.person.lastname}</div>;
-          }
-        }
-      `,
-      settings: {react: {flowVersion: '0.53'}},
-      errors: [{
-        message: '\'person.lastname\' is missing in props validation',
-        line: 7,
-        column: 50,
-        type: 'Identifier'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type Props = { foo: string }
-        function higherOrderComponent<Props>() {
-          return class extends React.Component<Props> {
-            render() {
-              return <div>{this.props.foo} - {this.props.bar}</div>
-            }
-          }
-        }
-      `,
-      errors: [{
-        message: '\'bar\' is missing in props validation'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        function higherOrderComponent<P: { foo: string }>() {
-          return class extends React.Component<P> {
-            render() {
-              return <div>{this.props.foo} - {this.props.bar}</div>
-            }
-          }
-        }
-      `,
-      errors: [{
-        message: '\'bar\' is missing in props validation'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        const withOverlayState = <P: {foo: string}>(WrappedComponent: ComponentType<P>): CpmponentType<P> => (
-          class extends React.Component<P> {
-            constructor(props) {
-              super(props);
-              this.state = {foo: props.foo, bar: props.bar}
-            }
-            render() {
-              return <div>Hello World</div>
-            }
-          }
-        )
-      `,
-      errors: [{
-        message: '\'bar\' is missing in props validation'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type PropsA = {foo: string };
-        type PropsB = { bar: string };
-        type Props = PropsA & PropsB;
-
-        class MyComponent extends React.Component {
-          props: Props;
-          
-          render() {
-            return <div>{this.props.foo} - {this.props.bar} - {this.props.fooBar}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint',
-      errors: [{
-        message: '\'fooBar\' is missing in props validation'
-      }]
-    }, {
-      code: `
-        type PropsA = { foo: string };
-        type PropsB = { bar: string };
-        type PropsC = { zap: string };
-        type Props = PropsA & PropsB;
-
-        class Bar extends React.Component {
-          props: Props & PropsC;
-          
-          render() {
-            return <div>{this.props.foo} - {this.props.bar} - {this.props.zap} - {this.props.fooBar}</div>
-          }
-        }
-      `,
-      parser: 'babel-eslint',
-      errors: [{
-        message: '\'fooBar\' is missing in props validation'
-      }]
-    }, {
-      code: `
-        type PropsB = { bar: string };
-        type PropsC = { zap: string };
-        type Props = PropsB & {
-          baz: string 
-        };
-
-        class Bar extends React.Component {
-          props: Props & PropsC;
-          
-          render() {
-            return <div>{this.props.bar} - {this.props.baz} - {this.props.fooBar}</div>
-          }
-        }
-      `,
-      errors: [{
-        message: '\'fooBar\' is missing in props validation'
-      }],
-      parser: 'babel-eslint'
-    }, {
-      code: `
-        type PropsB = { bar: string };
-        type PropsC = { zap: string };
-        type Props = {
-          baz: string 
-        } & PropsB;
-
-        class Bar extends React.Component {
-          props: Props & PropsC;
-          
-          render() {
-            return <div>{this.props.bar} - {this.props.baz} - {this.props.fooBar}</div>
-          }
-        }
-      `,
-      errors: [{
-        message: '\'fooBar\' is missing in props validation'
-      }],
-      parser: 'babel-eslint'
     }
   ]
 });
diff --git a/tests/lib/rules/require-default-props.js b/tests/lib/rules/require-default-props.js
index 7b50b780..b19b2b45 100644
--- a/tests/lib/rules/require-default-props.js
+++ b/tests/lib/rules/require-default-props.js
@@ -776,26 +776,6 @@ ruleTester.run('require-default-props', rule, {
         propWrapperFunctions: ['forbidExtraProps']
       }
     },
-    {
-      code: [
-        'function MyStatelessComponent({ foo, bar }) {',
-        '  return <div>{foo}{bar}</div>;',
-        '}',
-        'const propTypes = {',
-        '  foo: PropTypes.string,',
-        '  bar: PropTypes.string.isRequired',
-        '};',
-        'MyStatelessComponent.propTypes = forbidExtraProps(propTypes);'
-      ].join('\n'),
-      errors: [{
-        message: 'propType "foo" is not required, but has no corresponding defaultProp declaration.',
-        line: 5,
-        column: 3
-      }],
-      settings: {
-        propWrapperFunctions: ['forbidExtraProps']
-      }
-    },
     {
       code: [
         'function MyStatelessComponent({ foo, bar }) {',
@@ -1307,25 +1287,6 @@ ruleTester.run('require-default-props', rule, {
       }]
     },
 
-    // component with no declared props followed by a failing component
-    {
-      code: [
-        'var ComponentWithNoProps = ({ bar = "bar" }) => {',
-        '  return <div>Hello {this.props.foo}</div>;',
-        '}',
-        'var Greetings = ({ foo = "foo" }) => {',
-        '  return <div>Hello {this.props.foo}</div>;',
-        '}',
-        'Greetings.propTypes = {',
-        '  foo: PropTypes.string',
-        '};'
-      ].join('\n'),
-      errors: [{
-        message: 'propType "foo" is not required, but has no corresponding defaultProp declaration.',
-        line: 8,
-        column: 3
-      }]
-    },
     //
     // with Flow annotations
     {
diff --git a/tests/lib/rules/sort-prop-types.js b/tests/lib/rules/sort-prop-types.js
index 77be2845..ce97b0a0 100644
--- a/tests/lib/rules/sort-prop-types.js
+++ b/tests/lib/rules/sort-prop-types.js
@@ -316,15 +316,6 @@ ruleTester.run('sort-prop-types', rule, {
       '};',
       'TextFieldLabel.propTypes = propTypes;'
     ].join('\n')
-  }, {
-    code: [
-      'const First = (props) => <div />;',
-      'export const propTypes = {',
-      '    a: PropTypes.any,',
-      '    z: PropTypes.string,',
-      '};',
-      'First.propTypes = propTypes;'
-    ].join('\n')
   }],
 
   invalid: [{
@@ -572,42 +563,6 @@ ruleTester.run('sort-prop-types', rule, {
       column: 5,
       type: 'Property'
     }]
-  }, {
-    code: [
-      'const First = (props) => <div />;',
-      'const propTypes = {',
-      '    z: PropTypes.string,',
-      '    a: PropTypes.any,',
-      '};',
-      'First.propTypes = forbidExtraProps(propTypes);'
-    ].join('\n'),
-    settings: {
-      propWrapperFunctions: ['forbidExtraProps']
-    },
-    errors: [{
-      message: ERROR_MESSAGE,
-      line: 4,
-      column: 5,
-      type: 'Property'
-    }]
-  }, {
-    code: [
-      'const First = (props) => <div />;',
-      'const propTypes = {',
-      '    z: PropTypes.string,',
-      '    a: PropTypes.any,',
-      '};',
-      'First.propTypes = propTypes;'
-    ].join('\n'),
-    settings: {
-      propWrapperFunctions: ['forbidExtraProps']
-    },
-    errors: [{
-      message: ERROR_MESSAGE,
-      line: 4,
-      column: 5,
-      type: 'Property'
-    }]
   }, {
     code: [
       'var First = createReactClass({',