Repository: vuejs/eslint-plugin-vue
Pull request #794 (2019-01-31 14:44:50)

⭐️New: Add `vue/dot-location` rule
This PR adds the wrapper rule of the [dot-location](https://eslint.org/docs/rules/dot-location) core rule to apply to the expressions in `<template>`.


Patch:
diff --git a/README.md b/README.md
index 3552e99c..f5932178 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
 
 ## :book: Documentation
 
-See https://eslint.vuejs.org
+See [the official website](https://eslint.vuejs.org).
 
 ## :anchor: Versioning Policy
 
@@ -17,37 +17,37 @@ This plugin is following [Semantic Versioning](https://semver.org/) and [ESLint'
 
 ## :newspaper: Changelog
 
-We're using [GitHub Releases](https://github.com/vuejs/eslint-plugin-vue/releases).
+This project uses [GitHub Releases](https://github.com/vuejs/eslint-plugin-vue/releases).
 
-## :beers: Contribution guide
+## :beers: Contribution Guide
 
-Contributing is welcome!
+Contribution is welcome!
 
-See https://eslint.vuejs.org/developer-guide/
+See [The ESLint Vue Plugin Developer Guide](https://eslint.vuejs.org/developer-guide/).
 
-### Working with rules
+### Working with Rules
 
-Before you start writing new rule, please read the [official ESLint guide](https://eslint.org/docs/developer-guide/working-with-rules).
+Before you start writing a new rule, please read [the official ESLint guide](https://eslint.org/docs/developer-guide/working-with-rules).
 
-Next in order to get an idea how does the AST of the code that you want to check looks like, you can use one of the following applications:
-- [astexplorer.net](https://astexplorer.net/) - best tool to inspect ASTs, but it doesn't support Vue templates yet
-- [ast.js.org](https://ast.js.org/) - not fully featured, but supports Vue templates syntax
+Next, in order to get an idea how does the AST of the code that you want to check looks like, use one of the following applications:
+- [astexplorer.net](https://astexplorer.net/) - the best tool to inspect ASTs, but it doesn't support Vue template yet
+- [ast.js.org](https://ast.js.org/) - not fully featured, but supports Vue template syntax
 
-Since single file components in Vue are not plain JavaScript, we can't use the default parser, and we had to introduce additional one: `vue-eslint-parser`, that generates enhanced AST with nodes that represent specific parts of the template syntax, as well as what's inside the `<script>` tag.
+Since single file components in Vue are not plain JavaScript, the default parser couldn't be used, so a new one was introduced. `vue-eslint-parser` generates enhanced AST with nodes that represent specific parts of the template syntax, as well as what's inside the `<script>` tag.
 
 To know more about certain nodes in produced ASTs, go here:
 - [ESTree docs](https://github.com/estree/estree)
 - [vue-eslint-parser AST docs](https://github.com/mysticatea/vue-eslint-parser/blob/master/docs/ast.md)
 
-The `vue-eslint-parser` provides few useful parser services, to help traverse the produced AST and access tokens of the template:
+The `vue-eslint-parser` provides a few useful parser services that help traverse the produced AST and access tokens of the template:
 - `context.parserServices.defineTemplateBodyVisitor(visitor, scriptVisitor)`
 - `context.parserServices.getTemplateBodyTokenStore()`
 
-Check out an [example rule](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/mustache-interpolation-spacing.js) to get a better understanding of how these work.
+Check out [an example rule](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/mustache-interpolation-spacing.js) to get a better understanding of how these work.
 
-Please be aware that regarding what kind of code examples you'll write in tests, you'll have to accordingly setup the parser in `RuleTester` (you can do it on per test case basis though). [See an example here](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/attribute-hyphenation.js#L19)
+Please be aware that regarding what kind of code examples you'll write in tests, you'll have to accordingly set up the parser in `RuleTester` (you can do it on a per test case basis). See an example [here](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/attribute-hyphenation.js#L19).
 
-If you'll stuck, remember there are plenty of rules you can learn from already, and if you can't find the right solution - don't hesitate to reach out in issues. We're happy to help!
+If you'll stuck, remember there are plenty of rules you can learn from already. If you can't find the right solution, don't hesitate to reach out in [issues](https://github.com/vuejs/eslint-plugin-vue/issues) – we're happy to help!
 
 ## :lock: License
 
diff --git a/docs/.vuepress/components/eslint-code-block.vue b/docs/.vuepress/components/eslint-code-block.vue
index 13d824a5..ab33abdf 100644
--- a/docs/.vuepress/components/eslint-code-block.vue
+++ b/docs/.vuepress/components/eslint-code-block.vue
@@ -6,8 +6,8 @@
       :code="code"
       :style="{ height }"
       class="eslint-code-block"
-      filename="example.vue"
-      language="html"
+      :filename="filename"
+      :language="language"
       :preprocess="preprocess"
       :postprocess="postprocess"
       dark
@@ -36,6 +36,14 @@ export default {
       default () {
         return {}
       }
+    },
+    filename: {
+      type: String,
+      default: 'example.vue'
+    },
+    language: {
+      type: String,
+      default: 'html'
     }
   },
 
@@ -83,7 +91,10 @@ export default {
         parser: 'vue-eslint-parser',
         parserOptions: {
           ecmaVersion: 2019,
-          sourceType: 'module'
+          sourceType: 'module',
+          ecmaFeatures: {
+            jsx: true
+          }
         }
       }
     },
diff --git a/docs/rules/README.md b/docs/rules/README.md
index f7e7d7ec..82baedd0 100644
--- a/docs/rules/README.md
+++ b/docs/rules/README.md
@@ -146,15 +146,19 @@ For example:
 | [vue/camelcase](./camelcase.md) | enforce camelcase naming convention |  |
 | [vue/comma-dangle](./comma-dangle.md) | require or disallow trailing commas | :wrench: |
 | [vue/component-name-in-template-casing](./component-name-in-template-casing.md) | enforce specific casing for the component naming style in template | :wrench: |
+| [vue/dot-location](./dot-location.md) | enforce consistent newlines before and after dots | :wrench: |
 | [vue/eqeqeq](./eqeqeq.md) | require the use of `===` and `!==` | :wrench: |
 | [vue/key-spacing](./key-spacing.md) | enforce consistent spacing between keys and values in object literal properties | :wrench: |
 | [vue/match-component-file-name](./match-component-file-name.md) | require component name property to match its file name |  |
+| [vue/no-boolean-default](./no-boolean-default.md) | disallow boolean defaults | :wrench: |
+| [vue/no-empty-pattern](./no-empty-pattern.md) | disallow empty destructuring patterns |  |
 | [vue/no-restricted-syntax](./no-restricted-syntax.md) | disallow specified syntax |  |
 | [vue/object-curly-spacing](./object-curly-spacing.md) | enforce consistent spacing inside braces | :wrench: |
 | [vue/require-direct-export](./require-direct-export.md) | require the component to be directly exported |  |
 | [vue/script-indent](./script-indent.md) | enforce consistent indentation in `<script>` | :wrench: |
 | [vue/space-infix-ops](./space-infix-ops.md) | require spacing around infix operators | :wrench: |
 | [vue/space-unary-ops](./space-unary-ops.md) | enforce consistent spacing before or after unary operators | :wrench: |
+| [vue/v-on-function-call](./v-on-function-call.md) | enforce or forbid parentheses after method calls without arguments in `v-on` directives | :wrench: |
 
 ## Deprecated
 
diff --git a/docs/rules/attributes-order.md b/docs/rules/attributes-order.md
index cbd38eee..2f41dfa6 100644
--- a/docs/rules/attributes-order.md
+++ b/docs/rules/attributes-order.md
@@ -25,7 +25,7 @@ This rule aims to enforce ordering of component attributes. The default order is
 - `GLOBAL`
   ex: 'id'
 - `UNIQUE`
-  ex: 'ref', 'key', 'slot'
+  ex: 'ref', 'key', 'v-slot', 'slot'
 - `TWO_WAY_BINDING`
   ex: 'v-model'
 - `OTHER_DIRECTIVES`
diff --git a/docs/rules/dot-location.md b/docs/rules/dot-location.md
new file mode 100644
index 00000000..56a9c334
--- /dev/null
+++ b/docs/rules/dot-location.md
@@ -0,0 +1,23 @@
+---
+pageClass: rule-details
+sidebarDepth: 0
+title: vue/dot-location
+description: enforce consistent newlines before and after dots
+---
+# vue/dot-location
+> enforce consistent newlines before and after dots
+
+- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
+
+This rule is the same rule as core [dot-location] rule but it applies to the expressions in `<template>`.
+
+## :books: Further reading
+
+- [dot-location]
+
+[dot-location]: https://eslint.org/docs/rules/dot-location
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/dot-location.js)
+- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/dot-location.js)
diff --git a/docs/rules/match-component-file-name.md b/docs/rules/match-component-file-name.md
index 963295fe..961937b1 100644
--- a/docs/rules/match-component-file-name.md
+++ b/docs/rules/match-component-file-name.md
@@ -25,8 +25,7 @@ This rule has some options.
 }
 ```
 
-By default this rule will only verify components in a file with a `.jsx` 
-extension.
+By default this rule will only verify components in a file with a `.jsx` extension.
 
 You can use any combination of `".jsx"`, `".vue"` and `".js"` extensions.
 
@@ -34,130 +33,196 @@ You can also enforce same case between the component's name and its file name.
 
 If you are defining multiple components within the same file, this rule will be ignored.
 
-:-1: Examples of **incorrect** code for this rule:
+<eslint-code-block filename="src/MyComponent.jsx" language="javascript" :rules="{'vue/match-component-file-name': ['error']}">
 
 ```jsx
 // file name: src/MyComponent.jsx
 export default {
-  name: 'MComponent', // note the missing y
-  render: () {
+  /* ✓ GOOD */
+  name: 'MyComponent',
+  render() {
     return <h1>Hello world</h1>
   }
 }
 ```
 
-```vue
-// file name: src/MyComponent.vue
-// options: {extensions: ["vue"]}
-<script>
-  export default {
-    name: 'MComponent',
-    template: '<div />'
-  }
-</script>
-```
+</eslint-code-block>
 
-```js
-// file name: src/MyComponent.js
-// options: {extensions: ["js"]}
-new Vue({
-  name: 'MComponent',
-  template: '<div />'
-})
-```
-
-```js
-// file name: src/MyComponent.js
-// options: {extensions: ["js"]}
-Vue.component('MComponent', {
-  template: '<div />'
-})
-```
+<eslint-code-block filename="src/MyComponent.jsx" language="javascript" :rules="{'vue/match-component-file-name': ['error']}">
 
 ```jsx
 // file name: src/MyComponent.jsx
-// options: {shouldMatchCase: true}
 export default {
+  /* ✓ GOOD */
   name: 'my-component',
   render() { return <div /> }
 }
 ```
 
-```jsx
-// file name: src/my-component.jsx
-// options: {shouldMatchCase: true}
-export default {
-  name: 'MyComponent',
-  render() { return <div /> }
-}
-```
+</eslint-code-block>
 
-:+1: Examples of **correct** code for this rule:
+<eslint-code-block filename="src/MyComponent.jsx" language="javascript" :rules="{'vue/match-component-file-name': ['error']}">
 
 ```jsx
 // file name: src/MyComponent.jsx
 export default {
-  name: 'MyComponent',
-  render: () {
+  /* ✗ BAD */
+  name: 'MComponent', // note the missing y
+  render() {
     return <h1>Hello world</h1>
   }
 }
 ```
 
+</eslint-code-block>
+
+<eslint-code-block filename="src/MyComponent.jsx" language="javascript" :rules="{'vue/match-component-file-name': ['error']}">
+
 ```jsx
 // file name: src/MyComponent.jsx
-// no name property defined
+/* no name property defined */
 export default {
-  render: () {
+  render() {
     return <h1>Hello world</h1>
   }
 }
 ```
 
+</eslint-code-block>
+
+<eslint-code-block filename="src/MyComponent.vue" :rules="{'vue/match-component-file-name': ['error']}">
+
+```vue
+<!-- file name: src/MyComponent.vue -->
+<script>
+  export default {
+    /* The default does not verify to `.vue`. */
+    name: 'MComponent',
+    template: '<div />'
+  }
+</script>
+```
+
+</eslint-code-block>
+
+## :wrench: Options
+
+```json
+{
+  "vue/match-component-file-name": ["error", {
+    "extensions": ["jsx"],
+    "shouldMatchCase": false
+  }]
+}
+```
+
+- `"extensions": []` ... array of file extensions to be verified. Default is set to `["jsx"]`.
+- `"shouldMatchCase": false` ... boolean indicating if component's name
+  should also match its file name case. Default is set to `false`.
+
+### `{extensions: ["vue"]}`
+
+<eslint-code-block filename="src/MyComponent.vue" :rules="{'vue/match-component-file-name': ['error', {extensions: ['vue']}]}">
+
 ```vue
-// file name: src/MyComponent.vue
+<!-- file name: src/MyComponent.vue -->
 <script>
   export default {
+    /* ✓ GOOD */
     name: 'MyComponent',
     template: '<div />'
   }
 </script>
 ```
 
+</eslint-code-block>
+
+<eslint-code-block filename="src/MyComponent.vue" :rules="{'vue/match-component-file-name': ['error', {extensions: ['vue']}]}">
+
+```vue
+<!-- file name: src/MyComponent.vue -->
+<script>
+  export default {
+    /* ✗ BAD */
+    name: 'MComponent',
+    template: '<div />'
+  }
+</script>
+```
+
+</eslint-code-block>
+
+<eslint-code-block filename="src/MyComponent.vue" :rules="{'vue/match-component-file-name': ['error', {extensions: ['vue']}]}">
+
 ```vue
-// file name: src/MyComponent.vue
+<!-- file name: src/MyComponent.vue -->
 <script>
+  /* no name property defined */
   export default {
     template: '<div />'
   }
 </script>
 ```
 
+</eslint-code-block>
+
+### `{extensions: ["js"]}`
+
+<eslint-code-block filename="src/MyComponent.js" language="javascript" :rules="{'vue/match-component-file-name': ['error', {extensions: ['js']}]}">
+
 ```js
 // file name: src/MyComponent.js
 new Vue({
+  /* ✓ GOOD */
   name: 'MyComponent',
   template: '<div />'
 })
 ```
 
+</eslint-code-block>
+
+<eslint-code-block filename="src/MyComponent.js" language="javascript" :rules="{'vue/match-component-file-name': ['error', {extensions: ['js']}]}">
+
+```js
+// file name: src/MyComponent.js
+/* ✓ GOOD */
+Vue.component('MyComponent', {
+  template: '<div />'
+})
+```
+
+</eslint-code-block>
+
+<eslint-code-block filename="src/MyComponent.js" language="javascript" :rules="{'vue/match-component-file-name': ['error', {extensions: ['js']}]}">
+
 ```js
 // file name: src/MyComponent.js
 new Vue({
+  /* ✗ BAD */
+  name: 'MComponent',
   template: '<div />'
 })
 ```
 
+</eslint-code-block>
+
+<eslint-code-block filename="src/MyComponent.js" language="javascript" :rules="{'vue/match-component-file-name': ['error', {extensions: ['js']}]}">
+
 ```js
 // file name: src/MyComponent.js
-Vue.component('MyComponent', {
+/* ✗ BAD */
+Vue.component('MComponent', {
   template: '<div />'
 })
 ```
 
+</eslint-code-block>
+
+<eslint-code-block filename="src/components.js" language="javascript" :rules="{'vue/match-component-file-name': ['error', {extensions: ['js']}]}">
+
 ```js
 // file name: src/components.js
-// defines multiple components, so this rule is ignored
+/* defines multiple components, so this rule is ignored */
 Vue.component('MyComponent', {
   template: '<div />'
 })
@@ -172,38 +237,73 @@ new Vue({
 })
 ```
 
+</eslint-code-block>
+
+<eslint-code-block filename="src/MyComponent.js" language="javascript" :rules="{'vue/match-component-file-name': ['error', {extensions: ['js']}]}">
+
+```js
+// file name: src/MyComponent.js
+/* no name property defined */
+new Vue({
+  template: '<div />'
+})
+```
+
+</eslint-code-block>
+
+### `{shouldMatchCase: true}`
+
+<eslint-code-block filename="src/MyComponent.jsx" language="javascript" :rules="{'vue/match-component-file-name': ['error',  {shouldMatchCase: true}]}">
+
 ```jsx
 // file name: src/MyComponent.jsx
-// options: {shouldMatchCase: true}
 export default {
+  /* ✓ GOOD */
   name: 'MyComponent',
   render() { return <div /> }
 }
 ```
 
+</eslint-code-block>
+
+<eslint-code-block filename="src/my-component.jsx" language="javascript" :rules="{'vue/match-component-file-name': ['error',  {shouldMatchCase: true}]}">
+
 ```jsx
 // file name: src/my-component.jsx
-// options: {shouldMatchCase: true}
 export default {
+  /* ✓ GOOD */
   name: 'my-component',
   render() { return <div /> }
 }
 ```
 
-## :wrench: Options
+</eslint-code-block>
 
-```json
-{
-  "vue/match-component-file-name": ["error", {
-    "extensions": ["jsx"],
-    "shouldMatchCase": false
-  }]
+<eslint-code-block filename="src/MyComponent.jsx" language="javascript" :rules="{'vue/match-component-file-name': ['error', {shouldMatchCase: true}]}">
+
+```jsx
+// file name: src/MyComponent.jsx
+export default {
+  /* ✗ BAD */
+  name: 'my-component',
+  render() { return <div /> }
 }
 ```
 
-- `"extensions": []` ... array of file extensions to be verified. Default is set to `["jsx"]`.
-- `"shouldMatchCase": false` ... boolean indicating if component's name
-  should also match its file name case. Default is set to `false`.
+</eslint-code-block>
+
+<eslint-code-block filename="src/my-component.jsx" language="javascript" :rules="{'vue/match-component-file-name': ['error', {shouldMatchCase: true}]}">
+
+```jsx
+// file name: src/my-component.jsx
+export default {
+  /* ✗ BAD */
+  name: 'MyComponent',
+  render() { return <div /> }
+}
+```
+
+</eslint-code-block>
 
 ## :books: Further reading
 
diff --git a/docs/rules/multiline-html-element-content-newline.md b/docs/rules/multiline-html-element-content-newline.md
index 1004c1ee..c3eab2c2 100644
--- a/docs/rules/multiline-html-element-content-newline.md
+++ b/docs/rules/multiline-html-element-content-newline.md
@@ -74,11 +74,11 @@ This rule enforces a line break before and after the contents of a multiline ele
 
 ## :wrench: Options
 
-```json
+```js
 {
     "vue/multiline-html-element-content-newline": ["error", {
         "ignoreWhenEmpty": true,
-        "ignores": ["pre", "textarea"],
+        "ignores": ["pre", "textarea", ...INLINE_ELEMENTS],
         "allowEmptyLines": false
     }]
 }
@@ -86,11 +86,15 @@ This rule enforces a line break before and after the contents of a multiline ele
 
 - `ignoreWhenEmpty` ... disables reporting when element has no content.
     default `true`
-- `ignores` ... the configuration for element names to ignore line breaks style.  
-    default `["pre", "textarea"]`
+- `ignores` ... the configuration for element names to ignore line breaks style.
+    default `["pre", "textarea", ...INLINE_ELEMENTS]`.
 - `allowEmptyLines` ... if `true`, it allows empty lines around content. If you want to disallow multiple empty lines, use [no-multiple-empty-lines] in combination.  
     default `false`
 
+::: info
+  All inline non void elements can be found [here](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/utils/inline-non-void-elements.json).
+:::
+
 ### `"ignores": ["VueComponent", "pre", "textarea"]`
 
 <eslint-code-block fix :rules="{'vue/multiline-html-element-content-newline': ['error', { ignores: ['VueComponent', 'pre', 'textarea'] }]}">
diff --git a/docs/rules/no-boolean-default.md b/docs/rules/no-boolean-default.md
new file mode 100644
index 00000000..74e53f92
--- /dev/null
+++ b/docs/rules/no-boolean-default.md
@@ -0,0 +1,49 @@
+---
+pageClass: rule-details
+sidebarDepth: 0
+title: vue/no-boolean-default
+description: disallow boolean defaults
+---
+# vue/no-boolean-default
+> disallow boolean defaults
+
+- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
+
+The rule prevents Boolean props from having a default value.
+
+
+## :book: Rule Details
+The rule is to enforce the HTML standard of always defaulting boolean attributes to false.
+
+<eslint-code-block fix :rules="{'vue/no-boolean-default': ['error']}">
+
+```vue
+<script>
+export default {
+  props: {
+    foo: {
+      type: Boolean,
+      default: true
+    },
+    bar: {
+      type: Boolean
+    }
+  }
+}
+</script>
+```
+
+</eslint-code-block>
+
+## :wrench: Options
+- `'no-default'` (default) allows a prop definition object, but enforces that the `default` property not be defined.
+- `'default-false'` enforces that the default can be set but must be set to `false`.
+
+```json
+  "vue/no-boolean-default": ["error", "no-default|default-false"]
+```
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-boolean-default.js)
+- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-boolean-default.js)
diff --git a/docs/rules/no-empty-pattern.md b/docs/rules/no-empty-pattern.md
new file mode 100644
index 00000000..dd23c9f5
--- /dev/null
+++ b/docs/rules/no-empty-pattern.md
@@ -0,0 +1,21 @@
+---
+pageClass: rule-details
+sidebarDepth: 0
+title: vue/no-empty-pattern
+description: disallow empty destructuring patterns
+---
+# vue/no-empty-pattern
+> disallow empty destructuring patterns
+
+This rule is the same rule as core [no-empty-pattern] rule but it applies to the expressions in `<template>`.
+
+## :books: Further reading
+
+- [no-empty-pattern]
+
+[no-empty-pattern]: https://eslint.org/docs/rules/no-empty-pattern
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-empty-pattern.js)
+- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-empty-pattern.js)
diff --git a/docs/rules/no-unused-components.md b/docs/rules/no-unused-components.md
index 94d84a67..c63d98ba 100644
--- a/docs/rules/no-unused-components.md
+++ b/docs/rules/no-unused-components.md
@@ -74,7 +74,7 @@ This rule reports components that haven't been used in the template.
 </eslint-code-block>
 
 ::: warning Note
-Components registered under other than `PascalCase` name have to be called directly under the specified name, whereas if you register it using `PascalCase` you can call it however you like, except using `snake_case`.
+Components registered under `PascalCase` or `camelCase` names have may be called however you like, except using `snake_case`. Otherwise, they will need to be called directly under the specified name.
 :::
 
 ## :wrench: Options
diff --git a/docs/rules/singleline-html-element-content-newline.md b/docs/rules/singleline-html-element-content-newline.md
index 92f5f90d..6ff57bc5 100644
--- a/docs/rules/singleline-html-element-content-newline.md
+++ b/docs/rules/singleline-html-element-content-newline.md
@@ -50,12 +50,12 @@ This rule enforces a line break before and after the contents of a singleline el
 
 ## :wrench: Options
 
-```json
+```js
 {
   "vue/singleline-html-element-content-newline": ["error", {
     "ignoreWhenNoAttributes": true,
     "ignoreWhenEmpty": true,
-    "ignores": ["pre", "textarea"]
+    "ignores": ["pre", "textarea", ...INLINE_ELEMENTS]
   }]
 }
 ```
@@ -64,8 +64,13 @@ This rule enforces a line break before and after the contents of a singleline el
     default `true`
 - `ignoreWhenEmpty` ... disables reporting when element has no content.
     default `true`
-- `ignores` ... the configuration for element names to ignore line breaks style.  
-    default `["pre", "textarea"]`
+- `ignores` ... the configuration for element names to ignore line breaks style.
+    default `["pre", "textarea", ...INLINE_ELEMENTS]`.
+
+
+::: info
+  All inline non void elements can be found [here](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/utils/inline-non-void-elements.json).
+:::
 
 
 ### `"ignoreWhenNoAttributes": true`
diff --git a/docs/rules/v-on-function-call.md b/docs/rules/v-on-function-call.md
new file mode 100644
index 00000000..a3a5a3c8
--- /dev/null
+++ b/docs/rules/v-on-function-call.md
@@ -0,0 +1,77 @@
+---
+pageClass: rule-details
+sidebarDepth: 0
+title: vue/v-on-function-call
+description: enforce or forbid parentheses after method calls without arguments in `v-on` directives
+---
+# vue/v-on-function-call
+> enforce or forbid parentheses after method calls without arguments in `v-on` directives
+
+- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
+
+## :book: Rule Details
+
+:-1: Example of **incorrect** code for this rule:
+
+```html
+<button v-on:click="closeModal()">
+  Close
+</button>
+```
+
+:+1: Example of **correct** code for this rule:
+
+```html
+<button v-on:click="closeModal">
+  Close
+</button>
+```
+
+## :wrench: Options
+
+Default is set to `never`.
+
+```
+'vue/v-on-parens': [2, 'always'|'never']
+```
+
+### `"always"` - Always use parentheses in `v-on` directives
+
+:-1: Example of **incorrect** code:
+
+```html
+<button v-on:click="closeModal">
+  Close
+</button>
+```
+
+:+1: Example of **correct** code:
+
+```html
+<button v-on:click="closeModal()">
+  Close
+</button>
+```
+
+### `"never"` - Never use parentheses in `v-on` directives for method calls without arguments
+
+:-1: Example of **incorrect** code:
+
+```html
+<button v-on:click="closeModal()">
+  Close
+</button>
+```
+
+:+1: Example of **correct** code:
+
+```html
+<button v-on:click="closeModal">
+  Close
+</button>
+```
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/v-on-function-call.js)
+- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/v-on-function-call.js)
diff --git a/docs/rules/valid-v-else.md b/docs/rules/valid-v-else.md
index c632ca1e..3dcd4bb1 100644
--- a/docs/rules/valid-v-else.md
+++ b/docs/rules/valid-v-else.md
@@ -18,8 +18,8 @@ This rule reports `v-else` directives in the following cases:
 - The directive has that argument. E.g. `<div v-if="foo"></div><div v-else:aaa></div>`
 - The directive has that modifier. E.g. `<div v-if="foo"></div><div v-else.bbb></div>`
 - The directive has that attribute value. E.g. `<div v-if="foo"></div><div v-else="bar"></div>`
-- The directive is on the elements that the previous element don't have `v-if`/`v-if-else` directives. E.g. `<div v-else></div>`
-- The directive is on the elements which have `v-if`/`v-if-else` directives. E.g. `<div v-if="foo" v-else></div>`
+- The directive is on the elements that the previous element don't have `v-if`/`v-else-if` directives. E.g. `<div v-else></div>`
+- The directive is on the elements which have `v-if`/`v-else-if` directives. E.g. `<div v-if="foo" v-else></div>`
 
 <eslint-code-block :rules="{'vue/valid-v-else': ['error']}">
 
diff --git a/lib/configs/no-layout-rules.js b/lib/configs/no-layout-rules.js
index 2b23f1e6..b50aaddb 100644
--- a/lib/configs/no-layout-rules.js
+++ b/lib/configs/no-layout-rules.js
@@ -10,6 +10,7 @@ module.exports = {
     'vue/block-spacing': 'off',
     'vue/brace-style': 'off',
     'vue/comma-dangle': 'off',
+    'vue/dot-location': 'off',
     'vue/html-closing-bracket-newline': 'off',
     'vue/html-closing-bracket-spacing': 'off',
     'vue/html-indent': 'off',
diff --git a/lib/index.js b/lib/index.js
index 88173639..8dbae682 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -17,6 +17,7 @@ module.exports = {
     'comma-dangle': require('./rules/comma-dangle'),
     'comment-directive': require('./rules/comment-directive'),
     'component-name-in-template-casing': require('./rules/component-name-in-template-casing'),
+    'dot-location': require('./rules/dot-location'),
     'eqeqeq': require('./rules/eqeqeq'),
     'html-closing-bracket-newline': require('./rules/html-closing-bracket-newline'),
     'html-closing-bracket-spacing': require('./rules/html-closing-bracket-spacing'),
@@ -32,9 +33,11 @@ module.exports = {
     'mustache-interpolation-spacing': require('./rules/mustache-interpolation-spacing'),
     'name-property-casing': require('./rules/name-property-casing'),
     'no-async-in-computed-properties': require('./rules/no-async-in-computed-properties'),
+    'no-boolean-default': require('./rules/no-boolean-default'),
     'no-confusing-v-for-v-if': require('./rules/no-confusing-v-for-v-if'),
     'no-dupe-keys': require('./rules/no-dupe-keys'),
     'no-duplicate-attributes': require('./rules/no-duplicate-attributes'),
+    'no-empty-pattern': require('./rules/no-empty-pattern'),
     'no-multi-spaces': require('./rules/no-multi-spaces'),
     'no-parsing-error': require('./rules/no-parsing-error'),
     'no-reserved-keys': require('./rules/no-reserved-keys'),
@@ -68,6 +71,7 @@ module.exports = {
     'this-in-template': require('./rules/this-in-template'),
     'use-v-on-exact': require('./rules/use-v-on-exact'),
     'v-bind-style': require('./rules/v-bind-style'),
+    'v-on-function-call': require('./rules/v-on-function-call'),
     'v-on-style': require('./rules/v-on-style'),
     'valid-template-root': require('./rules/valid-template-root'),
     'valid-v-bind': require('./rules/valid-v-bind'),
diff --git a/lib/rules/array-bracket-spacing.js b/lib/rules/array-bracket-spacing.js
index e03abeb0..359a29c7 100644
--- a/lib/rules/array-bracket-spacing.js
+++ b/lib/rules/array-bracket-spacing.js
@@ -5,5 +5,8 @@
 
 const { wrapCoreRule } = require('../utils')
 
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/array-bracket-spacing'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+  require('eslint/lib/rules/array-bracket-spacing'),
+  { skipDynamicArguments: true }
+)
diff --git a/lib/rules/attribute-hyphenation.js b/lib/rules/attribute-hyphenation.js
index f2c95a52..2ead228b 100644
--- a/lib/rules/attribute-hyphenation.js
+++ b/lib/rules/attribute-hyphenation.js
@@ -92,7 +92,10 @@ module.exports = {
       VAttribute (node) {
         if (!utils.isCustomComponent(node.parent.parent)) return
 
-        const name = !node.directive ? node.key.rawName : node.key.name === 'bind' ? node.key.raw.argument : false
+        const name =
+          !node.directive ? node.key.rawName
+            : node.key.name.name === 'bind' ? node.key.argument && node.key.argument.rawName
+              : /* otherwise */ false
         if (!name || isIgnoredAttribute(name)) return
 
         reportIssue(node, name)
diff --git a/lib/rules/attributes-order.js b/lib/rules/attributes-order.js
index 8aec48c0..1808d381 100644
--- a/lib/rules/attributes-order.js
+++ b/lib/rules/attributes-order.js
@@ -9,8 +9,13 @@ const utils = require('../utils')
 // Rule Definition
 // ------------------------------------------------------------------------------
 
-function getAttributeType (name, isDirective) {
-  if (isDirective) {
+function getAttributeType (attribute, sourceCode) {
+  const isBind = attribute.directive && attribute.key.name.name === 'bind'
+  const name = isBind
+    ? (attribute.key.argument ? sourceCode.getText(attribute.key.argument) : '')
+    : (attribute.directive ? attribute.key.name.name : attribute.key.name)
+
+  if (attribute.directive && !isBind) {
     if (name === 'for') {
       return 'LIST_RENDERING'
     } else if (name === 'if' || name === 'else-if' || name === 'else' || name === 'show' || name === 'cloak') {
@@ -23,6 +28,8 @@ function getAttributeType (name, isDirective) {
       return 'EVENTS'
     } else if (name === 'html' || name === 'text') {
       return 'CONTENT'
+    } else if (name === 'slot') {
+      return 'UNIQUE'
     } else {
       return 'OTHER_DIRECTIVES'
     }
@@ -38,10 +45,9 @@ function getAttributeType (name, isDirective) {
     }
   }
 }
-function getPosition (attribute, attributePosition) {
-  const attributeType = attribute.directive && attribute.key.name === 'bind'
-    ? getAttributeType(attribute.key.argument, false)
-    : getAttributeType(attribute.key.name, attribute.directive)
+
+function getPosition (attribute, attributePosition, sourceCode) {
+  const attributeType = getAttributeType(attribute, sourceCode)
   return attributePosition.hasOwnProperty(attributeType) ? attributePosition[attributeType] : -1
 }
 
@@ -91,8 +97,8 @@ function create (context) {
       previousNode = null
     },
     'VAttribute' (node) {
-      if ((currentPosition === -1) || (currentPosition <= getPosition(node, attributePosition))) {
-        currentPosition = getPosition(node, attributePosition)
+      if ((currentPosition === -1) || (currentPosition <= getPosition(node, attributePosition, sourceCode))) {
+        currentPosition = getPosition(node, attributePosition, sourceCode)
         previousNode = node
       } else {
         reportIssue(node, previousNode)
diff --git a/lib/rules/block-spacing.js b/lib/rules/block-spacing.js
index 7cee5235..6877ce31 100644
--- a/lib/rules/block-spacing.js
+++ b/lib/rules/block-spacing.js
@@ -5,5 +5,8 @@
 
 const { wrapCoreRule } = require('../utils')
 
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/block-spacing'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+  require('eslint/lib/rules/block-spacing'),
+  { skipDynamicArguments: true }
+)
diff --git a/lib/rules/brace-style.js b/lib/rules/brace-style.js
index c64880ba..4d0999dd 100644
--- a/lib/rules/brace-style.js
+++ b/lib/rules/brace-style.js
@@ -5,5 +5,9 @@
 
 const { wrapCoreRule } = require('../utils')
 
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/brace-style'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+  require('eslint/lib/rules/brace-style'),
+  { skipDynamicArguments: true }
+)
+
diff --git a/lib/rules/dot-location.js b/lib/rules/dot-location.js
new file mode 100644
index 00000000..c8889bb6
--- /dev/null
+++ b/lib/rules/dot-location.js
@@ -0,0 +1,9 @@
+/**
+ * @author Yosuke Ota
+ */
+'use strict'
+
+const { wrapCoreRule } = require('../utils')
+
+// eslint-disable-next-line
+module.exports = wrapCoreRule(require('eslint/lib/rules/dot-location'))
diff --git a/lib/rules/key-spacing.js b/lib/rules/key-spacing.js
index c7c46fcf..5dd81f5f 100644
--- a/lib/rules/key-spacing.js
+++ b/lib/rules/key-spacing.js
@@ -5,5 +5,8 @@
 
 const { wrapCoreRule } = require('../utils')
 
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/key-spacing'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+  require('eslint/lib/rules/key-spacing'),
+  { skipDynamicArguments: true }
+)
diff --git a/lib/rules/max-attributes-per-line.js b/lib/rules/max-attributes-per-line.js
index f9f4deb8..eca53345 100644
--- a/lib/rules/max-attributes-per-line.js
+++ b/lib/rules/max-attributes-per-line.js
@@ -67,6 +67,7 @@ module.exports = {
   },
 
   create: function (context) {
+    const sourceCode = context.getSourceCode()
     const configuration = parseOptions(context.options[0])
     const multilineMaximum = configuration.multiline
     const singlelinemMaximum = configuration.singleline
@@ -130,23 +131,6 @@ module.exports = {
       return defaults
     }
 
-    function getPropData (prop) {
-      let propType = 'Attribute'
-      let propName = prop.key.name
-
-      if (utils.isBindingAttribute(prop)) {
-        propType = 'Binding'
-        propName = prop.key.raw.argument
-      } else if (utils.isEventAttribute(prop)) {
-        propType = 'Event'
-        propName = prop.key.raw.argument
-      } else if (prop.directive) {
-        propType = 'Directive'
-      }
-
-      return { propType, propName }
-    }
-
     function showErrors (attributes) {
       attributes.forEach((prop, i) => {
         const fix = (fixer) => {
@@ -166,8 +150,8 @@ module.exports = {
         context.report({
           node: prop,
           loc: prop.loc,
-          message: '{{propType}} "{{propName}}" should be on a new line.',
-          data: getPropData(prop),
+          message: '\'{{name}}\' should be on a new line.',
+          data: { name: sourceCode.getText(prop.key) },
           fix
         })
       })
diff --git a/lib/rules/multiline-html-element-content-newline.js b/lib/rules/multiline-html-element-content-newline.js
index 8e900b6e..6b7e5248 100644
--- a/lib/rules/multiline-html-element-content-newline.js
+++ b/lib/rules/multiline-html-element-content-newline.js
@@ -10,6 +10,7 @@
 
 const utils = require('../utils')
 const casing = require('../utils/casing')
+const INLINE_ELEMENTS = require('../utils/inline-non-void-elements.json')
 
 // ------------------------------------------------------------------------------
 // Helpers
@@ -21,7 +22,7 @@ function isMultilineElement (element) {
 
 function parseOptions (options) {
   return Object.assign({
-    ignores: ['pre', 'textarea'],
+    ignores: ['pre', 'textarea'].concat(INLINE_ELEMENTS),
     ignoreWhenEmpty: true,
     allowEmptyLines: false
   }, options)
diff --git a/lib/rules/no-async-in-computed-properties.js b/lib/rules/no-async-in-computed-properties.js
index 9a55cd40..b61c8ca4 100644
--- a/lib/rules/no-async-in-computed-properties.js
+++ b/lib/rules/no-async-in-computed-properties.js
@@ -138,8 +138,11 @@ module.exports = {
 
         'ReturnStatement' (node) {
           if (
-            node.argument.type === 'ObjectExpression' ||
-            node.argument.type === 'ArrayExpression'
+            node.argument &&
+            (
+              node.argument.type === 'ObjectExpression' ||
+              node.argument.type === 'ArrayExpression'
+            )
           ) {
             allowedScopes.push(node.argument)
           }
diff --git a/lib/rules/no-boolean-default.js b/lib/rules/no-boolean-default.js
new file mode 100644
index 00000000..5b436b72
--- /dev/null
+++ b/lib/rules/no-boolean-default.js
@@ -0,0 +1,95 @@
+/**
+ * @fileoverview Prevents boolean defaults from being set
+ * @author Hiroki Osame
+ */
+'use strict'
+
+const utils = require('../utils')
+
+// ------------------------------------------------------------------------------
+// Rule Definition
+// ------------------------------------------------------------------------------
+
+function isBooleanProp (prop) {
+  return (
+    prop.type === 'Property' &&
+    prop.key.type === 'Identifier' &&
+    prop.key.name === 'type' &&
+    prop.value.type === 'Identifier' &&
+    prop.value.name === 'Boolean'
+  )
+}
+
+function getBooleanProps (props) {
+  return props
+    .filter(prop => (
+      prop.value &&
+      prop.value.properties &&
+      prop.value.properties.find(isBooleanProp)
+    ))
+}
+
+function getDefaultNode (propDef) {
+  return propDef.value.properties.find(p => {
+    return (
+      p.type === 'Property' &&
+      p.key.type === 'Identifier' &&
+      p.key.name === 'default'
+    )
+  })
+}
+
+module.exports = {
+  meta: {
+    type: 'suggestion',
+    docs: {
+      description: 'disallow boolean defaults',
+      category: undefined,
+      url: 'https://eslint.vuejs.org/rules/no-boolean-default.html'
+    },
+    fixable: 'code',
+    schema: [
+      {
+        enum: ['default-false', 'no-default']
+      }
+    ]
+  },
+
+  create (context) {
+    return utils.executeOnVueComponent(context, (obj) => {
+      const props = utils.getComponentProps(obj)
+      const booleanProps = getBooleanProps(props)
+
+      if (!booleanProps.length) return
+
+      const booleanType = context.options[0] || 'no-default'
+
+      booleanProps.forEach((propDef) => {
+        const defaultNode = getDefaultNode(propDef)
+
+        switch (booleanType) {
+          case 'no-default':
+            if (defaultNode) {
+              context.report({
+                node: defaultNode,
+                message: 'Boolean prop should not set a default (Vue defaults it to false).'
+              })
+            }
+            break
+
+          case 'default-false':
+            if (
+              defaultNode &&
+              defaultNode.value.value !== false
+            ) {
+              context.report({
+                node: defaultNode,
+                message: 'Boolean prop should only be defaulted to false.'
+              })
+            }
+            break
+        }
+      })
+    })
+  }
+}
diff --git a/lib/rules/no-confusing-v-for-v-if.js b/lib/rules/no-confusing-v-for-v-if.js
index 2ab0188b..0102ad55 100644
--- a/lib/rules/no-confusing-v-for-v-if.js
+++ b/lib/rules/no-confusing-v-for-v-if.js
@@ -50,7 +50,7 @@ module.exports = {
 
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='if']" (node) {
+      "VAttribute[directive=true][key.name.name='if']" (node) {
         const element = node.parent.parent
 
         if (utils.hasDirective(element, 'for') && !isUsingIterationVar(node)) {
diff --git a/lib/rules/no-duplicate-attributes.js b/lib/rules/no-duplicate-attributes.js
index a0bd3f90..d3c20c6e 100644
--- a/lib/rules/no-duplicate-attributes.js
+++ b/lib/rules/no-duplicate-attributes.js
@@ -24,8 +24,8 @@ function getName (attribute) {
   if (!attribute.directive) {
     return attribute.key.name
   }
-  if (attribute.key.name === 'bind') {
-    return attribute.key.argument || null
+  if (attribute.key.name.name === 'bind') {
+    return (attribute.key.argument && attribute.key.argument.name) || null
   }
   return null
 }
diff --git a/lib/rules/no-empty-pattern.js b/lib/rules/no-empty-pattern.js
new file mode 100644
index 00000000..daa5b1c2
--- /dev/null
+++ b/lib/rules/no-empty-pattern.js
@@ -0,0 +1,9 @@
+/**
+ * @author Yosuke Ota
+ */
+'use strict'
+
+const { wrapCoreRule } = require('../utils')
+
+// eslint-disable-next-line
+module.exports = wrapCoreRule(require('eslint/lib/rules/no-empty-pattern'))
diff --git a/lib/rules/no-unused-components.js b/lib/rules/no-unused-components.js
index 4382cbbc..bf012d55 100644
--- a/lib/rules/no-unused-components.js
+++ b/lib/rules/no-unused-components.js
@@ -55,8 +55,12 @@ module.exports = {
 
         usedComponents.add(node.rawName)
       },
-      "VAttribute[directive=true][key.name='bind'][key.argument='is']" (node) {
-        if (node.value.type !== 'VExpressionContainer') return
+      "VAttribute[directive=true][key.name.name='bind'][key.argument.name='is']" (node) {
+        if (
+          !node.value ||  // `<component :is>`
+          node.value.type !== 'VExpressionContainer' ||
+          !node.value.expression  // `<component :is="">`
+        ) return
 
         if (node.value.expression.type === 'Literal') {
           usedComponents.add(node.value.expression.value)
diff --git a/lib/rules/no-use-v-if-with-v-for.js b/lib/rules/no-use-v-if-with-v-for.js
index ef3a19aa..754086f7 100644
--- a/lib/rules/no-use-v-if-with-v-for.js
+++ b/lib/rules/no-use-v-if-with-v-for.js
@@ -70,7 +70,7 @@ module.exports = {
     const options = context.options[0] || {}
     const allowUsingIterationVar = options.allowUsingIterationVar === true // default false
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='if']" (node) {
+      "VAttribute[directive=true][key.name.name='if']" (node) {
         const element = node.parent.parent
 
         if (utils.hasDirective(element, 'for')) {
diff --git a/lib/rules/no-v-html.js b/lib/rules/no-v-html.js
index 17a47921..878bbbd0 100644
--- a/lib/rules/no-v-html.js
+++ b/lib/rules/no-v-html.js
@@ -22,7 +22,7 @@ module.exports = {
   },
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='html']" (node) {
+      "VAttribute[directive=true][key.name.name='html']" (node) {
         context.report({
           node,
           loc: node.loc,
diff --git a/lib/rules/object-curly-spacing.js b/lib/rules/object-curly-spacing.js
index fc41b0d3..db049bbf 100644
--- a/lib/rules/object-curly-spacing.js
+++ b/lib/rules/object-curly-spacing.js
@@ -5,5 +5,8 @@
 
 const { wrapCoreRule } = require('../utils')
 
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/object-curly-spacing'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+  require('eslint/lib/rules/object-curly-spacing'),
+  { skipDynamicArguments: true }
+)
diff --git a/lib/rules/order-in-components.js b/lib/rules/order-in-components.js
index d41798c8..a63b477e 100644
--- a/lib/rules/order-in-components.js
+++ b/lib/rules/order-in-components.js
@@ -22,6 +22,8 @@ const defaultOrder = [
   'data',
   'computed',
   'watch',
+  'asyncData',
+  'fetch',
   'LIFECYCLE_HOOKS',
   'methods',
   ['template', 'render'],
diff --git a/lib/rules/require-default-prop.js b/lib/rules/require-default-prop.js
index 6520f5fd..91dd9084 100644
--- a/lib/rules/require-default-prop.js
+++ b/lib/rules/require-default-prop.js
@@ -141,11 +141,13 @@ module.exports = {
       const propsToReport = excludeBooleanProps(propsWithoutDefault)
 
       for (const prop of propsToReport) {
+        const propName = prop.propName != null ? prop.propName : `[${context.getSourceCode().getText(prop.key)}]`
+
         context.report({
           node: prop.node,
           message: `Prop '{{propName}}' requires default value to be set.`,
           data: {
-            propName: prop.key.name
+            propName
           }
         })
       }
diff --git a/lib/rules/require-v-for-key.js b/lib/rules/require-v-for-key.js
index 6de38f7e..6a71e3ac 100644
--- a/lib/rules/require-v-for-key.js
+++ b/lib/rules/require-v-for-key.js
@@ -49,7 +49,7 @@ module.exports = {
     }
 
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='for']" (node) {
+      "VAttribute[directive=true][key.name.name='for']" (node) {
         checkKey(node.parent.parent)
       }
     })
diff --git a/lib/rules/require-valid-default-prop.js b/lib/rules/require-valid-default-prop.js
index 4880c3a6..b1b938d6 100644
--- a/lib/rules/require-valid-default-prop.js
+++ b/lib/rules/require-valid-default-prop.js
@@ -109,11 +109,12 @@ module.exports = {
         const defType = getValueType(def.value)
         if (!defType || typeNames.has(defType)) continue
 
+        const propName = prop.propName != null ? prop.propName : `[${context.getSourceCode().getText(prop.key)}]`
         context.report({
           node: def,
           message: "Type of the default value for '{{name}}' prop must be a {{types}}.",
           data: {
-            name: prop.key.name,
+            name: propName,
             types: Array.from(typeNames).join(' or ').toLowerCase()
           }
         })
diff --git a/lib/rules/singleline-html-element-content-newline.js b/lib/rules/singleline-html-element-content-newline.js
index 5cf4e0f7..f6202519 100644
--- a/lib/rules/singleline-html-element-content-newline.js
+++ b/lib/rules/singleline-html-element-content-newline.js
@@ -10,6 +10,7 @@
 
 const utils = require('../utils')
 const casing = require('../utils/casing')
+const INLINE_ELEMENTS = require('../utils/inline-non-void-elements.json')
 
 // ------------------------------------------------------------------------------
 // Helpers
@@ -21,7 +22,7 @@ function isSinglelineElement (element) {
 
 function parseOptions (options) {
   return Object.assign({
-    ignores: ['pre', 'textarea'],
+    ignores: ['pre', 'textarea'].concat(INLINE_ELEMENTS),
     ignoreWhenNoAttributes: true,
     ignoreWhenEmpty: true
   }, options)
diff --git a/lib/rules/space-infix-ops.js b/lib/rules/space-infix-ops.js
index fb94b74b..25100468 100644
--- a/lib/rules/space-infix-ops.js
+++ b/lib/rules/space-infix-ops.js
@@ -5,5 +5,8 @@
 
 const { wrapCoreRule } = require('../utils')
 
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/space-infix-ops'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+  require('eslint/lib/rules/space-infix-ops'),
+  { skipDynamicArguments: true }
+)
diff --git a/lib/rules/space-unary-ops.js b/lib/rules/space-unary-ops.js
index 41960792..787aae6b 100644
--- a/lib/rules/space-unary-ops.js
+++ b/lib/rules/space-unary-ops.js
@@ -5,5 +5,8 @@
 
 const { wrapCoreRule } = require('../utils')
 
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/space-unary-ops'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+  require('eslint/lib/rules/space-unary-ops'),
+  { skipDynamicArguments: true }
+)
diff --git a/lib/rules/this-in-template.js b/lib/rules/this-in-template.js
index 0f96402e..6e972ee9 100644
--- a/lib/rules/this-in-template.js
+++ b/lib/rules/this-in-template.js
@@ -84,6 +84,11 @@ module.exports = {
       }
       : {
         'VExpressionContainer' (node) {
+          if (node.parent.type === 'VDirectiveKey') {
+            // We cannot use `.` in dynamic arguments because the right of the `.` becomes a modifier.
+            // For example, In `:[this.prop]` case, `:[this` is an argument and `prop]` is a modifier.
+            return
+          }
           if (node.references) {
             for (const reference of node.references) {
               if (!scope.nodes.some(el => el.name === reference.id.name)) {
diff --git a/lib/rules/use-v-on-exact.js b/lib/rules/use-v-on-exact.js
index 3e110ec2..bf194fd8 100644
--- a/lib/rules/use-v-on-exact.js
+++ b/lib/rules/use-v-on-exact.js
@@ -20,18 +20,19 @@ const SYSTEM_MODIFIERS = new Set(['ctrl', 'shift', 'alt', 'meta'])
  * Finds and returns all keys for event directives
  *
  * @param {array} attributes Element attributes
+ * @param {SourceCode} sourceCode The source code object.
  * @returns {array[object]} [{ name, node, modifiers }]
  */
-function getEventDirectives (attributes) {
+function getEventDirectives (attributes, sourceCode) {
   return attributes
     .filter(attribute =>
       attribute.directive &&
-      attribute.key.name === 'on'
+      attribute.key.name.name === 'on'
     )
     .map(attribute => ({
-      name: attribute.key.argument,
+      name: attribute.key.argument ? sourceCode.getText(attribute.key.argument) : '',
       node: attribute.key,
-      modifiers: attribute.key.modifiers
+      modifiers: attribute.key.modifiers.map(modifier => modifier.name)
     }))
 }
 
@@ -149,12 +150,14 @@ module.exports = {
    * @returns {Object} AST event handlers.
    */
   create (context) {
+    const sourceCode = context.getSourceCode()
+
     return utils.defineTemplateBodyVisitor(context, {
       VStartTag (node) {
         if (node.attributes.length === 0) return
 
         const isCustomComponent = utils.isCustomComponent(node.parent)
-        let events = getEventDirectives(node.attributes)
+        let events = getEventDirectives(node.attributes, sourceCode)
 
         if (isCustomComponent) {
           // For components consider only events with `native` modifier
diff --git a/lib/rules/v-bind-style.js b/lib/rules/v-bind-style.js
index e2e81361..a5025ee6 100644
--- a/lib/rules/v-bind-style.js
+++ b/lib/rules/v-bind-style.js
@@ -30,23 +30,42 @@ module.exports = {
   },
 
   create (context) {
-    const shorthand = context.options[0] !== 'longform'
+    const preferShorthand = context.options[0] !== 'longform'
 
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='bind'][key.argument!=null]" (node) {
-        if (node.key.shorthand === shorthand) {
+      "VAttribute[directive=true][key.name.name='bind'][key.argument!=null]" (node) {
+        const shorthandProp = node.key.name.rawName === '.'
+        const shorthand = node.key.name.rawName === ':' || shorthandProp
+        if (shorthand === preferShorthand) {
           return
         }
 
         context.report({
           node,
           loc: node.loc,
-          message: shorthand
-            ? "Unexpected 'v-bind' before ':'."
-            : "Expected 'v-bind' before ':'.",
-          fix: (fixer) => shorthand
-            ? fixer.removeRange([node.range[0], node.range[0] + 6])
-            : fixer.insertTextBefore(node, 'v-bind')
+          message:
+            preferShorthand ? "Unexpected 'v-bind' before ':'."
+              : shorthandProp ? "Expected 'v-bind:' instead of '.'."
+              /* otherwise */ : "Expected 'v-bind' before ':'.",
+          * fix (fixer) {
+            if (preferShorthand) {
+              yield fixer.remove(node.key.name)
+            } else {
+              yield fixer.insertTextBefore(node, 'v-bind')
+
+              if (shorthandProp) {
+                // Replace `.` by `:`.
+                yield fixer.replaceText(node.key.name, ':')
+
+                // Insert `.prop` modifier if it doesn't exist.
+                const modifier = node.key.modifiers[0]
+                const isAutoGeneratedPropModifier = modifier.name === 'prop' && modifier.rawName === ''
+                if (isAutoGeneratedPropModifier) {
+                  yield fixer.insertTextBefore(modifier, '.prop')
+                }
+              }
+            }
+          }
         })
       }
     })
diff --git a/lib/rules/v-on-function-call.js b/lib/rules/v-on-function-call.js
new file mode 100644
index 00000000..e044cf13
--- /dev/null
+++ b/lib/rules/v-on-function-call.js
@@ -0,0 +1,60 @@
+/**
+ * @author Niklas Higi
+ */
+'use strict'
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+const utils = require('../utils')
+
+// ------------------------------------------------------------------------------
+// Rule Definition
+// ------------------------------------------------------------------------------
+
+module.exports = {
+  meta: {
+    type: 'suggestion',
+    docs: {
+      description: 'enforce or forbid parentheses after method calls without arguments in `v-on` directives',
+      category: undefined,
+      url: 'https://eslint.vuejs.org/rules/v-on-function-call.html'
+    },
+    fixable: 'code',
+    schema: [
+      { enum: ['always', 'never'] }
+    ]
+  },
+
+  create (context) {
+    const always = context.options[0] === 'always'
+
+    return utils.defineTemplateBodyVisitor(context, {
+      "VAttribute[directive=true][key.name.name='on'][key.argument!=null] > VExpressionContainer > Identifier" (node) {
+        if (!always) return
+        context.report({
+          node,
+          loc: node.loc,
+          message: "Method calls inside of 'v-on' directives must have parentheses."
+        })
+      },
+
+      "VAttribute[directive=true][key.name.name='on'][key.argument!=null] VOnExpression > ExpressionStatement > *" (node) {
+        if (!always && node.type === 'CallExpression' && node.arguments.length === 0) {
+          context.report({
+            node,
+            loc: node.loc,
+            message: "Method calls without arguments inside of 'v-on' directives must not have parentheses.",
+            fix: fixer => {
+              const nodeString = context.getSourceCode().getText().substring(node.range[0], node.range[1])
+              // This ensures that parens are also removed if they contain whitespace
+              const parensLength = nodeString.match(/\(\s*\)\s*$/)[0].length
+              return fixer.removeRange([node.end - parensLength, node.end])
+            }
+          })
+        }
+      }
+    })
+  }
+}
diff --git a/lib/rules/v-on-style.js b/lib/rules/v-on-style.js
index a767ef1b..191a12fc 100644
--- a/lib/rules/v-on-style.js
+++ b/lib/rules/v-on-style.js
@@ -30,11 +30,12 @@ module.exports = {
   },
 
   create (context) {
-    const shorthand = context.options[0] !== 'longform'
+    const preferShorthand = context.options[0] !== 'longform'
 
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='on'][key.argument!=null]" (node) {
-        if (node.key.shorthand === shorthand) {
+      "VAttribute[directive=true][key.name.name='on'][key.argument!=null]" (node) {
+        const shorthand = node.key.name.rawName === '@'
+        if (shorthand === preferShorthand) {
           return
         }
 
@@ -42,10 +43,10 @@ module.exports = {
         context.report({
           node,
           loc: node.loc,
-          message: shorthand
+          message: preferShorthand
             ? "Expected '@' instead of 'v-on:'."
             : "Expected 'v-on:' instead of '@'.",
-          fix: (fixer) => shorthand
+          fix: (fixer) => preferShorthand
             ? fixer.replaceTextRange([pos, pos + 5], '@')
             : fixer.replaceTextRange([pos, pos + 1], 'v-on:')
         })
diff --git a/lib/rules/valid-v-bind.js b/lib/rules/valid-v-bind.js
index ce47a1db..f8bc3519 100644
--- a/lib/rules/valid-v-bind.js
+++ b/lib/rules/valid-v-bind.js
@@ -35,14 +35,14 @@ module.exports = {
 
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='bind']" (node) {
+      "VAttribute[directive=true][key.name.name='bind']" (node) {
         for (const modifier of node.key.modifiers) {
-          if (!VALID_MODIFIERS.has(modifier)) {
+          if (!VALID_MODIFIERS.has(modifier.name)) {
             context.report({
               node,
               loc: node.key.loc,
               message: "'v-bind' directives don't support the modifier '{{name}}'.",
-              data: { name: modifier }
+              data: { name: modifier.name }
             })
           }
         }
diff --git a/lib/rules/valid-v-cloak.js b/lib/rules/valid-v-cloak.js
index b64e6c6b..b1676a08 100644
--- a/lib/rules/valid-v-cloak.js
+++ b/lib/rules/valid-v-cloak.js
@@ -29,7 +29,7 @@ module.exports = {
 
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='cloak']" (node) {
+      "VAttribute[directive=true][key.name.name='cloak']" (node) {
         if (node.key.argument) {
           context.report({
             node,
diff --git a/lib/rules/valid-v-else-if.js b/lib/rules/valid-v-else-if.js
index 67c5a05c..a4b5987e 100644
--- a/lib/rules/valid-v-else-if.js
+++ b/lib/rules/valid-v-else-if.js
@@ -29,7 +29,7 @@ module.exports = {
 
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='else-if']" (node) {
+      "VAttribute[directive=true][key.name.name='else-if']" (node) {
         const element = node.parent.parent
 
         if (!utils.prevElementHasIf(element)) {
diff --git a/lib/rules/valid-v-else.js b/lib/rules/valid-v-else.js
index d2d63a9e..e5412237 100644
--- a/lib/rules/valid-v-else.js
+++ b/lib/rules/valid-v-else.js
@@ -29,7 +29,7 @@ module.exports = {
 
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='else']" (node) {
+      "VAttribute[directive=true][key.name.name='else']" (node) {
         const element = node.parent.parent
 
         if (!utils.prevElementHasIf(element)) {
diff --git a/lib/rules/valid-v-for.js b/lib/rules/valid-v-for.js
index 75edaf07..28cf30c1 100644
--- a/lib/rules/valid-v-for.js
+++ b/lib/rules/valid-v-for.js
@@ -117,7 +117,7 @@ module.exports = {
     const sourceCode = context.getSourceCode()
 
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='for']" (node) {
+      "VAttribute[directive=true][key.name.name='for']" (node) {
         const element = node.parent.parent
 
         checkKey(context, node, element)
diff --git a/lib/rules/valid-v-html.js b/lib/rules/valid-v-html.js
index 9ec65933..1aeaeef1 100644
--- a/lib/rules/valid-v-html.js
+++ b/lib/rules/valid-v-html.js
@@ -29,7 +29,7 @@ module.exports = {
 
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='html']" (node) {
+      "VAttribute[directive=true][key.name.name='html']" (node) {
         if (node.key.argument) {
           context.report({
             node,
diff --git a/lib/rules/valid-v-if.js b/lib/rules/valid-v-if.js
index e08ccac2..40e9259c 100644
--- a/lib/rules/valid-v-if.js
+++ b/lib/rules/valid-v-if.js
@@ -29,7 +29,7 @@ module.exports = {
 
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='if']" (node) {
+      "VAttribute[directive=true][key.name.name='if']" (node) {
         const element = node.parent.parent
 
         if (utils.hasDirective(element, 'else')) {
diff --git a/lib/rules/valid-v-model.js b/lib/rules/valid-v-model.js
index b9e16ab3..d969f2c0 100644
--- a/lib/rules/valid-v-model.js
+++ b/lib/rules/valid-v-model.js
@@ -91,7 +91,7 @@ module.exports = {
 
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='model']" (node) {
+      "VAttribute[directive=true][key.name.name='model']" (node) {
         const element = node.parent.parent
         const name = element.name
 
@@ -121,12 +121,12 @@ module.exports = {
         }
 
         for (const modifier of node.key.modifiers) {
-          if (!VALID_MODIFIERS.has(modifier)) {
+          if (!VALID_MODIFIERS.has(modifier.name)) {
             context.report({
               node,
               loc: node.loc,
               message: "'v-model' directives don't support the modifier '{{name}}'.",
-              data: { name: modifier }
+              data: { name: modifier.name }
             })
           }
         }
diff --git a/lib/rules/valid-v-on.js b/lib/rules/valid-v-on.js
index 76034844..37e531f5 100644
--- a/lib/rules/valid-v-on.js
+++ b/lib/rules/valid-v-on.js
@@ -27,7 +27,8 @@ const VERB_MODIFIERS = new Set([
 // https://www.w3.org/TR/uievents-key/
 const KEY_ALIASES = new Set(keyAliases)
 
-function isValidModifier (modifier, customModifiers) {
+function isValidModifier (modifierNode, customModifiers) {
+  const modifier = modifierNode.name
   return (
     // built-in aliases
     VALID_MODIFIERS.has(modifier) ||
@@ -74,21 +75,21 @@ module.exports = {
     const sourceCode = context.getSourceCode()
 
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='on']" (node) {
+      "VAttribute[directive=true][key.name.name='on']" (node) {
         for (const modifier of node.key.modifiers) {
           if (!isValidModifier(modifier, customModifiers)) {
             context.report({
               node,
               loc: node.loc,
               message: "'v-on' directives don't support the modifier '{{modifier}}'.",
-              data: { modifier }
+              data: { modifier: modifier.name }
             })
           }
         }
 
         if (
           !utils.hasAttributeValue(node) &&
-          !node.key.modifiers.some(VERB_MODIFIERS.has, VERB_MODIFIERS)
+          !node.key.modifiers.some(modifier => VERB_MODIFIERS.has(modifier.name))
         ) {
           if (node.value && sourceCode.getText(node.value.expression)) {
             const value = sourceCode.getText(node.value)
diff --git a/lib/rules/valid-v-once.js b/lib/rules/valid-v-once.js
index f294a809..e0ada555 100644
--- a/lib/rules/valid-v-once.js
+++ b/lib/rules/valid-v-once.js
@@ -29,7 +29,7 @@ module.exports = {
 
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='once']" (node) {
+      "VAttribute[directive=true][key.name.name='once']" (node) {
         if (node.key.argument) {
           context.report({
             node,
diff --git a/lib/rules/valid-v-pre.js b/lib/rules/valid-v-pre.js
index eaf4ef03..40231a46 100644
--- a/lib/rules/valid-v-pre.js
+++ b/lib/rules/valid-v-pre.js
@@ -29,7 +29,7 @@ module.exports = {
 
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='pre']" (node) {
+      "VAttribute[directive=true][key.name.name='pre']" (node) {
         if (node.key.argument) {
           context.report({
             node,
diff --git a/lib/rules/valid-v-show.js b/lib/rules/valid-v-show.js
index 0855e92c..6eb5183c 100644
--- a/lib/rules/valid-v-show.js
+++ b/lib/rules/valid-v-show.js
@@ -29,7 +29,7 @@ module.exports = {
 
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='show']" (node) {
+      "VAttribute[directive=true][key.name.name='show']" (node) {
         if (node.key.argument) {
           context.report({
             node,
diff --git a/lib/rules/valid-v-text.js b/lib/rules/valid-v-text.js
index d1f823da..c23d1f1d 100644
--- a/lib/rules/valid-v-text.js
+++ b/lib/rules/valid-v-text.js
@@ -29,7 +29,7 @@ module.exports = {
 
   create (context) {
     return utils.defineTemplateBodyVisitor(context, {
-      "VAttribute[directive=true][key.name='text']" (node) {
+      "VAttribute[directive=true][key.name.name='text']" (node) {
         if (node.key.argument) {
           context.report({
             node,
diff --git a/lib/utils/indent-common.js b/lib/utils/indent-common.js
index 28e68b0a..227e85ad 100644
--- a/lib/utils/indent-common.js
+++ b/lib/utils/indent-common.js
@@ -879,13 +879,13 @@ module.exports.defineVisitor = function create (context, tokenStore, defaultOpti
   return processIgnores({
     VAttribute (node) {
       const keyToken = tokenStore.getFirstToken(node)
-      const eqToken = tokenStore.getFirstToken(node, 1)
+      const eqToken = tokenStore.getTokenAfter(node.key)
 
-      if (eqToken != null) {
+      if (eqToken != null && eqToken.range[1] <= node.range[1]) {
         setOffset(eqToken, 1, keyToken)
 
-        const valueToken = tokenStore.getFirstToken(node, 2)
-        if (valueToken != null) {
+        const valueToken = tokenStore.getTokenAfter(eqToken)
+        if (valueToken != null && valueToken.range[1] <= node.range[1]) {
           setOffset(valueToken, 1, keyToken)
         }
       }
diff --git a/lib/utils/index.js b/lib/utils/index.js
index e2af0257..d6c9221a 100644
--- a/lib/utils/index.js
+++ b/lib/utils/index.js
@@ -65,10 +65,13 @@ module.exports = {
   /**
    * Wrap a given core rule to apply it to Vue.js template.
    * @param {Rule} coreRule The core rule implementation to wrap.
-   * @param {string|undefined} category The category of this rule.
+   * @param {Object|undefined} options The option of this rule.
+   * @param {string|undefined} options.category The category of this rule.
+   * @param {boolean|undefined} options.skipDynamicArguments If `true`, skip validation within dynamic arguments.
    * @returns {Rule} The wrapped rule implementation.
    */
-  wrapCoreRule (coreRule, category) {
+  wrapCoreRule (coreRule, options) {
+    const { category, skipDynamicArguments } = options || {}
     return {
       create (context) {
         const tokenStore =
@@ -92,6 +95,19 @@ module.exports = {
           delete handlers['Program:exit']
         }
 
+        if (skipDynamicArguments) {
+          let withinDynamicArguments = false
+          for (const name of Object.keys(handlers)) {
+            const original = handlers[name]
+            handlers[name] = (...args) => {
+              if (withinDynamicArguments) return
+              original(...args)
+            }
+          }
+          handlers['VDirectiveKey > VExpressionContainer'] = () => { withinDynamicArguments = true }
+          handlers['VDirectiveKey > VExpressionContainer:exit'] = () => { withinDynamicArguments = false }
+        }
+
         // Apply the handlers to templates.
         return module.exports.defineTemplateBodyVisitor(context, handlers)
       },
@@ -140,25 +156,6 @@ module.exports = {
     return null
   },
 
-  /**
-   * Finds attribute in the given start tag
-   * @param {ASTNode} node The start tag node to check.
-   * @param {string} name The attribute name to check.
-   * @param {string} [value] The attribute value to check.
-   * @returns {ASTNode} attribute node
-   */
-  findAttribute (node, name, value) {
-    assert(node && node.type === 'VElement')
-    return node.startTag.attributes.find(attr => (
-      !attr.directive &&
-      attr.key.name === name &&
-      (
-        value === undefined ||
-        (attr.value != null && attr.value.value === value)
-      )
-    ))
-  },
-
   /**
    * Check whether the given start tag has specific directive.
    * @param {ASTNode} node The start tag node to check.
@@ -168,23 +165,7 @@ module.exports = {
    */
   hasAttribute (node, name, value) {
     assert(node && node.type === 'VElement')
-    return Boolean(this.findAttribute(node, name, value))
-  },
-
-  /**
-   * Finds directive in the given start tag
-   * @param {ASTNode} node The start tag node to check.
-   * @param {string} name The directive name to check.
-   * @param {string} [argument] The directive argument to check.
-   * @returns {ASTNode} directive node
-   */
-  findDirective (node, name, argument) {
-    assert(node && node.type === 'VElement')
-    return node.startTag.attributes.find(a =>
-      a.directive &&
-      a.key.name === name &&
-      (argument === undefined || a.key.argument === argument)
-    )
+    return Boolean(this.getAttribute(node, name, value))
   },
 
   /**
@@ -196,7 +177,7 @@ module.exports = {
    */
   hasDirective (node, name, argument) {
     assert(node && node.type === 'VElement')
-    return Boolean(this.findDirective(node, name, argument))
+    return Boolean(this.getDirective(node, name, argument))
   },
 
   /**
@@ -242,8 +223,8 @@ module.exports = {
     assert(node && node.type === 'VElement')
     return node.startTag.attributes.find(a =>
       a.directive &&
-      a.key.name === name &&
-      (argument === undefined || a.key.argument === argument)
+      a.key.name.name === name &&
+      (argument === undefined || (a.key.argument && a.key.argument.name) === argument)
     )
   },
 
@@ -265,10 +246,11 @@ module.exports = {
 
     return componentsNode.value.properties
       .filter(p => p.type === 'Property')
-      .map(node => ({
-        node,
-        name: this.getStaticPropertyName(node.key)
-      }))
+      .map(node => {
+        const name = this.getStaticPropertyName(node)
+        return name ? { node, name } : null
+      })
+      .filter(comp => comp != null)
   },
 
   /**
@@ -284,7 +266,7 @@ module.exports = {
       prev != null &&
       prev.startTag.attributes.some(a =>
         a.directive &&
-        (a.key.name === 'if' || a.key.name === 'else-if')
+        (a.key.name.name === 'if' || a.key.name.name === 'else-if')
       )
     )
   },
@@ -369,26 +351,6 @@ module.exports = {
     return VOID_ELEMENT_NAMES.has(name)
   },
 
-  /**
-   * Check whether the given attribute node is a binding
-   * @param {ASTNode} attribute The attribute to check.
-   * @returns {boolean}
-   */
-  isBindingAttribute (attribute) {
-    return attribute.directive &&
-      attribute.key.name === 'bind' &&
-      attribute.key.argument
-  },
-
-  /**
-   * Check whether the given attribute node is an event
-   * @param {ASTNode} name The attribute to check.
-   * @returns {boolean}
-   */
-  isEventAttribute (attribute) {
-    return attribute.directive && attribute.key.name === 'on'
-  },
-
   /**
    * Parse member expression node to get array with all of its parts
    * @param {ASTNode} node MemberExpression
@@ -484,13 +446,16 @@ module.exports = {
       props = propsNode.value.properties
         .filter(prop => prop.type === 'Property')
         .map(prop => {
-          return { key: prop.key, value: this.unwrapTypes(prop.value), node: prop }
+          return {
+            key: prop.key, value: this.unwrapTypes(prop.value), node: prop,
+            propName: this.getStaticPropertyName(prop)
+          }
         })
     } else {
       props = propsNode.value.elements
         .map(prop => {
           const key = prop.type === 'Literal' && typeof prop.value === 'string' ? prop : null
-          return { key, value: null, node: prop }
+          return { key, value: null, node: prop, propName: key != null ? prop.value : null }
         })
     }
 
diff --git a/lib/utils/inline-non-void-elements.json b/lib/utils/inline-non-void-elements.json
new file mode 100644
index 00000000..b3dda839
--- /dev/null
+++ b/lib/utils/inline-non-void-elements.json
@@ -0,0 +1,40 @@
+[
+  "a",
+  "abbr",
+  "audio",
+  "b",
+  "bdi",
+  "bdo",
+  "canvas",
+  "cite",
+  "code",
+  "data",
+  "del",
+  "dfn",
+  "em",
+  "i",
+  "iframe",
+  "ins",
+  "kbd",
+  "label",
+  "map",
+  "mark",
+  "noscript",
+  "object",
+  "output",
+  "picture",
+  "q",
+  "ruby",
+  "s",
+  "samp",
+  "small",
+  "span",
+  "strong",
+  "sub",
+  "sup",
+  "svg",
+  "time",
+  "u",
+  "var",
+  "video"
+]
diff --git a/package.json b/package.json
index afa4e756..33932c78 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-vue",
-  "version": "5.1.0",
+  "version": "5.2.2",
   "description": "Official ESLint plugin for Vue.js",
   "main": "lib/index.js",
   "scripts": {
@@ -46,7 +46,7 @@
     "eslint": "^5.0.0"
   },
   "dependencies": {
-    "vue-eslint-parser": "^5.0.0"
+    "vue-eslint-parser": "^6.0.2"
   },
   "devDependencies": {
     "@types/node": "^4.2.16",


Test patch:
diff --git a/tests/fixtures/script-indent/export-named-declaration-02.vue b/tests/fixtures/script-indent/export-named-declaration-02.vue
index 32c52653..00dbf3f3 100644
--- a/tests/fixtures/script-indent/export-named-declaration-02.vue
+++ b/tests/fixtures/script-indent/export-named-declaration-02.vue
@@ -1,5 +1,6 @@
 <!--{}-->
 <script>
+var a, b, c, d
 export
 {
   a
diff --git a/tests/fixtures/script-indent/export-specifier-01.vue b/tests/fixtures/script-indent/export-specifier-01.vue
index 00d1ead3..f38443bf 100644
--- a/tests/fixtures/script-indent/export-specifier-01.vue
+++ b/tests/fixtures/script-indent/export-specifier-01.vue
@@ -1,5 +1,6 @@
 <!--{}-->
 <script>
+var foo, bar
 export
 {
   foo
diff --git a/tests/lib/rules/array-bracket-spacing.js b/tests/lib/rules/array-bracket-spacing.js
index 509ebb1d..2aafe9ba 100644
--- a/tests/lib/rules/array-bracket-spacing.js
+++ b/tests/lib/rules/array-bracket-spacing.js
@@ -21,19 +21,32 @@ tester.run('array-bracket-spacing', rule, {
     {
       code: '<template><div :attr="[ a ]" /></template>',
       options: ['always']
+    },
+    '<template><div :[attr]="a" /></template>',
+    {
+      code: '<template><div :[attr]="a" /></template>',
+      options: ['always']
+    },
+    '<template><div :[[attr]]="a" /></template>',
+    {
+      code: '<template><div :[[attr]]="a" /></template>',
+      options: ['always']
     }
   ],
   invalid: [
     {
       code: '<template><div :attr="[ a]" /></template>',
+      output: '<template><div :attr="[a]" /></template>',
       errors: ["There should be no space after '['."]
     },
     {
       code: '<template><div :attr="[a ]" /></template>',
+      output: '<template><div :attr="[a]" /></template>',
       errors: ["There should be no space before ']'."]
     },
     {
       code: '<template><div :attr="[ a ]" /></template>',
+      output: '<template><div :attr="[a]" /></template>',
       errors: [
         "There should be no space after '['.",
         "There should be no space before ']'."
@@ -42,16 +55,19 @@ tester.run('array-bracket-spacing', rule, {
     {
       code: '<template><div :attr="[ a]" /></template>',
       options: ['never'],
+      output: '<template><div :attr="[a]" /></template>',
       errors: ["There should be no space after '['."]
     },
     {
       code: '<template><div :attr="[a ]" /></template>',
       options: ['never'],
+      output: '<template><div :attr="[a]" /></template>',
       errors: ["There should be no space before ']'."]
     },
     {
       code: '<template><div :attr="[ a ]" /></template>',
       options: ['never'],
+      output: '<template><div :attr="[a]" /></template>',
       errors: [
         "There should be no space after '['.",
         "There should be no space before ']'."
@@ -60,16 +76,28 @@ tester.run('array-bracket-spacing', rule, {
     {
       code: '<template><div :attr="[ a]" /></template>',
       options: ['always'],
+      output: '<template><div :attr="[ a ]" /></template>',
       errors: ["A space is required before ']'."]
     },
     {
       code: '<template><div :attr="[a ]" /></template>',
       options: ['always'],
+      output: '<template><div :attr="[ a ]" /></template>',
       errors: ["A space is required after '['."]
     },
     {
       code: '<template><div :attr="[a]" /></template>',
       options: ['always'],
+      output: '<template><div :attr="[ a ]" /></template>',
+      errors: [
+        "A space is required after '['.",
+        "A space is required before ']'."
+      ]
+    },
+    {
+      code: '<template><div :[[attr]]="[a]" /></template>',
+      options: ['always'],
+      output: '<template><div :[[attr]]="[ a ]" /></template>',
       errors: [
         "A space is required after '['.",
         "A space is required before ']'."
diff --git a/tests/lib/rules/attribute-hyphenation.js b/tests/lib/rules/attribute-hyphenation.js
index 433a3382..e5aad05e 100644
--- a/tests/lib/rules/attribute-hyphenation.js
+++ b/tests/lib/rules/attribute-hyphenation.js
@@ -47,6 +47,16 @@ ruleTester.run('attribute-hyphenation', rule, {
       filename: 'test.vue',
       code: '<template><custom data-id="foo" aria-test="bar" slot-scope="{ data }" custom-hyphen="foo" second-custom="bar"><a onClick="" my-prop="prop"></a></custom></template>',
       options: ['never', { 'ignore': ['custom-hyphen', 'second-custom'] }]
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><my-component :[fooBar]></my-component></template>',
+      options: ['always']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><my-component :[foo-bar]></my-component></template>',
+      options: ['never']
     }
   ],
 
diff --git a/tests/lib/rules/attributes-order.js b/tests/lib/rules/attributes-order.js
index d3629441..48e70e60 100644
--- a/tests/lib/rules/attributes-order.js
+++ b/tests/lib/rules/attributes-order.js
@@ -276,6 +276,23 @@ tester.run('attributes-order', rule, {
             'GLOBAL'
           ]
         }]
+    },
+    {
+      filename: 'test.vue',
+      code:
+        `<template>
+          <div
+            id="uniqueID"
+            ref="header"
+            :prop="headerData"
+            :[a+b]="headerData"
+            :[prop]="headerData"
+            myProp="prop"
+            v-on:click="functionCall"
+            v-on:[c]="functionCall"
+            v-text="textContent">
+          </div>
+        </template>`
     }
   ],
 
@@ -584,6 +601,32 @@ tester.run('attributes-order', rule, {
           nodeType: 'VIdentifier'
         }
       ]
+    },
+    {
+      code:
+        `<template>
+          <my-component
+            v-if="!visible"
+            v-model="content"
+            v-slot="textContent"
+            >
+          </my-component>
+        </template>`,
+      output:
+        `<template>
+          <my-component
+            v-if="!visible"
+            v-slot="textContent"
+            v-model="content"
+            >
+          </my-component>
+        </template>`,
+      errors: [
+        {
+          message: 'Attribute "v-slot" should go before "v-model".',
+          nodeType: 'VIdentifier'
+        }
+      ]
     }
   ]
 })
diff --git a/tests/lib/rules/block-spacing.js b/tests/lib/rules/block-spacing.js
index 8ffc55d6..ff3b4400 100644
--- a/tests/lib/rules/block-spacing.js
+++ b/tests/lib/rules/block-spacing.js
@@ -17,7 +17,8 @@ tester.run('block-spacing', rule, {
     {
       code: '<template><div :attr="function foo() {return true;}" /></template>',
       options: ['never']
-    }
+    },
+    '<template><div :[(function(){return(1)})()]="a" /></template>'
   ],
   invalid: [
     {
@@ -110,6 +111,27 @@ tester.run('block-spacing', rule, {
           line: 3
         }
       ]
+    },
+    {
+      code: '<template><div :[(function(){return(1)})()]="(function(){return(1)})()" /></template>',
+      output: '<template><div :[(function(){return(1)})()]="(function(){ return(1) })()" /></template>',
+      errors: [
+        {
+          messageId: 'missing',
+          data: {
+            location: 'after',
+            token: '{'
+          }
+          // message: 'Requires a space after \'{\'',
+        },
+        {
+          messageId: 'missing',
+          data: {
+            location: 'before',
+            token: '}'
+          }
+          // message: 'Requires a space before \'}\'',
+        }]
     }
   ]
 })
diff --git a/tests/lib/rules/brace-style.js b/tests/lib/rules/brace-style.js
index cd4f3d36..d8278e77 100644
--- a/tests/lib/rules/brace-style.js
+++ b/tests/lib/rules/brace-style.js
@@ -19,7 +19,8 @@ tester.run('brace-style', rule, {
     {
       code: `<template><div :attr="function foo() { return true; }" /></template>`,
       options: ['1tbs', { 'allowSingleLine': true }]
-    }
+    },
+    `<template><div :[(function(){return(1)})()]="a" /></template>`
   ],
   invalid: [
     {
@@ -64,6 +65,19 @@ tester.run('brace-style', rule, {
           line: 3
         }
       ]
+    },
+    {
+      code: '<template><div :[(function(){return(1)})()]="(function(){return(1)})()" /></template>',
+      output: `<template><div :[(function(){return(1)})()]="(function(){
+return(1)
+})()" /></template>`,
+      errors: [
+        {
+          message: 'Statement inside of curly braces should be on next line.'
+        },
+        {
+          message: 'Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.'
+        }]
     }
   ]
 })
diff --git a/tests/lib/rules/comma-dangle.js b/tests/lib/rules/comma-dangle.js
index aca71019..1d5c3e7b 100644
--- a/tests/lib/rules/comma-dangle.js
+++ b/tests/lib/rules/comma-dangle.js
@@ -33,6 +33,19 @@ tester.run('comma-dangle', rule, {
       options: [{
         'arrays': 'ignore'
       }]
+    },
+    {
+      code: `
+      <template>
+        <button :[[a,b][1]]="a" ></button>
+      </template>`
+    },
+    {
+      code: `
+      <template>
+        <button :[[a,b,][1]]="a" ></button>
+      </template>`,
+      options: ['always']
     }
   ],
   invalid: [
@@ -103,6 +116,37 @@ tester.run('comma-dangle', rule, {
           line: 7
         }
       ]
+    },
+    {
+      code: `
+      <template>
+        <button :[[a,b,][1]]="a" ></button>
+      </template>`,
+      output: `
+      <template>
+        <button :[[a,b][1]]="a" ></button>
+      </template>`,
+      errors: [
+        {
+          message: 'Unexpected trailing comma.'
+        }
+      ]
+    },
+    {
+      code: `
+      <template>
+        <button :[[a,b][1]]="a" ></button>
+      </template>`,
+      output: `
+      <template>
+        <button :[[a,b,][1]]="a" ></button>
+      </template>`,
+      options: ['always'],
+      errors: [
+        {
+          message: 'Missing trailing comma.'
+        }
+      ]
     }
   ]
 })
diff --git a/tests/lib/rules/dot-location.js b/tests/lib/rules/dot-location.js
new file mode 100644
index 00000000..2bc4a4ec
--- /dev/null
+++ b/tests/lib/rules/dot-location.js
@@ -0,0 +1,80 @@
+/**
+ * @author Yosuke Ota
+ */
+'use strict'
+
+const RuleTester = require('eslint').RuleTester
+const rule = require('../../../lib/rules/dot-location')
+
+const tester = new RuleTester({
+  parser: 'vue-eslint-parser',
+  parserOptions: { ecmaVersion: 2015 }
+})
+
+tester.run('dot-location', rule, {
+  valid: [
+    `<template>
+      <div
+        :attr="foo.
+          bar"
+      />
+    </template>`,
+    {
+      code: `
+      <template>
+        <div
+          :attr="foo
+            .bar"
+        />
+      </template>`,
+      options: ['property']
+    }
+  ],
+  invalid: [
+    {
+      code: `
+      <template>
+        <div
+          :attr="foo
+            .bar"
+        />
+      </template>`,
+      output: `
+      <template>
+        <div
+          :attr="foo.
+            bar"
+        />
+      </template>`,
+      errors: [
+        {
+          message: 'Expected dot to be on same line as object.',
+          line: 5
+        }
+      ]
+    },
+    {
+      code: `
+      <template>
+        <div
+          :attr="foo.
+            bar"
+        />
+      </template>`,
+      options: ['property'],
+      output: `
+      <template>
+        <div
+          :attr="foo
+            .bar"
+        />
+      </template>`,
+      errors: [
+        {
+          message: 'Expected dot to be on same line as property.',
+          line: 4
+        }
+      ]
+    }
+  ]
+})
diff --git a/tests/lib/rules/key-spacing.js b/tests/lib/rules/key-spacing.js
index 52adaaf9..167e1f38 100644
--- a/tests/lib/rules/key-spacing.js
+++ b/tests/lib/rules/key-spacing.js
@@ -13,15 +13,30 @@ const tester = new RuleTester({
 
 tester.run('key-spacing', rule, {
   valid: [
-    '<template><div :attr="{a: 1}" /></template>'
+    '<template><div :attr="{a: 1}" /></template>',
+    '<template><div :[{a:1}[`a`]]="a" /></template>',
+    {
+      code: '<template><div :[{a:1}[`a`]]="a" /></template>',
+      options: [{ 'beforeColon': true }]
+    }
   ],
   invalid: [
     {
       code: '<template><div :attr="{a :1}" /></template>',
+      output: '<template><div :attr="{a: 1}" /></template>',
       errors: [
         "Extra space after key 'a'.",
         "Missing space before value for key 'a'."
       ]
+    },
+    {
+      code: '<template><div :[{a:1}[`a`]]="{a:1}[`a`]" /></template>',
+      options: [{ 'beforeColon': true }],
+      output: '<template><div :[{a:1}[`a`]]="{a : 1}[`a`]" /></template>',
+      errors: [
+        "Missing space after key 'a'.",
+        "Missing space before value for key 'a'."
+      ]
     }
   ]
 })
diff --git a/tests/lib/rules/max-attributes-per-line.js b/tests/lib/rules/max-attributes-per-line.js
index ce4d45ff..38249265 100644
--- a/tests/lib/rules/max-attributes-per-line.js
+++ b/tests/lib/rules/max-attributes-per-line.js
@@ -93,43 +93,43 @@ ruleTester.run('max-attributes-per-line', rule, {
       code: `<template><component name="John Doe" age="30"></component></template>`,
       output: `<template><component name="John Doe"
 age="30"></component></template>`,
-      errors: ['Attribute "age" should be on a new line.']
+      errors: ['\'age\' should be on a new line.']
     },
     {
       code: `<template><component :name="user.name" :age="user.age"></component></template>`,
       output: `<template><component :name="user.name"
 :age="user.age"></component></template>`,
-      errors: ['Binding "age" should be on a new line.']
+      errors: ['\':age\' should be on a new line.']
     },
     {
       code: `<template><component :is="test" v-bind="user"></component></template>`,
       output: `<template><component :is="test"
 v-bind="user"></component></template>`,
-      errors: ['Directive "bind" should be on a new line.']
+      errors: ['\'v-bind\' should be on a new line.']
     },
     {
       code: `<template><component :name="user.name" @buy="buyProduct"></component></template>`,
       output: `<template><component :name="user.name"
 @buy="buyProduct"></component></template>`,
-      errors: ['Event "buy" should be on a new line.']
+      errors: ['\'@buy\' should be on a new line.']
     },
     {
       code: `<template><component :name="user.name" @click.stop></component></template>`,
       output: `<template><component :name="user.name"
 @click.stop></component></template>`,
-      errors: ['Event "click" should be on a new line.']
+      errors: ['\'@click.stop\' should be on a new line.']
     },
     {
       code: `<template><component :name="user.name" v-if="something"></component></template>`,
       output: `<template><component :name="user.name"
 v-if="something"></component></template>`,
-      errors: ['Directive "if" should be on a new line.']
+      errors: ['\'v-if\' should be on a new line.']
     },
     {
       code: `<template><component name="John Doe"    v-bind:age="user.age"></component></template>`,
       output: `<template><component name="John Doe"
 v-bind:age="user.age"></component></template>`,
-      errors: ['Binding "age" should be on a new line.']
+      errors: ['\'v-bind:age\' should be on a new line.']
     },
     {
       code: `<template><component job="Vet"
@@ -144,7 +144,7 @@ job="Vet"
         </component>
       </template>`,
       errors: [{
-        message: 'Attribute "job" should be on a new line.',
+        message: '\'job\' should be on a new line.',
         type: 'VAttribute',
         line: 1
       }]
@@ -155,7 +155,7 @@ job="Vet"
       output: `<template><component name="John Doe" age="30"
 job="Vet"></component></template>`,
       errors: [{
-        message: 'Attribute "job" should be on a new line.',
+        message: '\'job\' should be on a new line.',
         type: 'VAttribute',
         line: 1
       }]
@@ -166,11 +166,11 @@ job="Vet"></component></template>`,
       output: `<template><component name="John Doe"
 age="30" job="Vet"></component></template>`,
       errors: [{
-        message: 'Attribute "age" should be on a new line.',
+        message: '\'age\' should be on a new line.',
         type: 'VAttribute',
         line: 1
       }, {
-        message: 'Attribute "job" should be on a new line.',
+        message: '\'job\' should be on a new line.',
         type: 'VAttribute',
         line: 1
       }]
@@ -187,7 +187,7 @@ name="John Doe"
         </component>
       </template>`,
       errors: [{
-        message: 'Attribute "name" should be on a new line.',
+        message: '\'name\' should be on a new line.',
         type: 'VAttribute',
         line: 1
       }]
@@ -206,7 +206,7 @@ age="30"
         </component>
       </template>`,
       errors: [{
-        message: 'Attribute "age" should be on a new line.',
+        message: '\'age\' should be on a new line.',
         type: 'VAttribute',
         line: 2
       }]
@@ -225,7 +225,7 @@ age="30"
         </component>
       </template>`,
       errors: [{
-        message: 'Attribute "age" should be on a new line.',
+        message: '\'age\' should be on a new line.',
         type: 'VAttribute',
         line: 2
       }]
@@ -244,7 +244,7 @@ petname="Snoopy">
         </component>
       </template>`,
       errors: [{
-        message: 'Attribute "petname" should be on a new line.',
+        message: '\'petname\' should be on a new line.',
         type: 'VAttribute',
         line: 3
       }]
@@ -263,11 +263,11 @@ petname="Snoopy" extra="foo">
         </component>
       </template>`,
       errors: [{
-        message: 'Attribute "petname" should be on a new line.',
+        message: '\'petname\' should be on a new line.',
         type: 'VAttribute',
         line: 3
       }, {
-        message: 'Attribute "extra" should be on a new line.',
+        message: '\'extra\' should be on a new line.',
         type: 'VAttribute',
         line: 3
       }]
diff --git a/tests/lib/rules/multiline-html-element-content-newline.js b/tests/lib/rules/multiline-html-element-content-newline.js
index 8f2f707b..a99591dd 100644
--- a/tests/lib/rules/multiline-html-element-content-newline.js
+++ b/tests/lib/rules/multiline-html-element-content-newline.js
@@ -44,7 +44,8 @@ tester.run('multiline-html-element-content-newline', rule, {
         <div class="panel">
           content
         </div>
-      </template>`,
+      </template>
+    `,
     `
       <template>
         <div
@@ -52,7 +53,71 @@ tester.run('multiline-html-element-content-newline', rule, {
         >
           content
         </div>
-      </template>`,
+      </template>
+    `,
+    `
+      <template>
+        <a
+          href="/"
+          class="link"
+        >Home</a>
+      </template>
+    `,
+    `
+      <template>
+        <a
+          href="/"
+          class="link"
+        >Home
+        </a>
+      </template>
+    `,
+    `
+      <template>
+        <a
+          href="/"
+          class="link"
+        >
+          Home
+        </a>
+      </template>
+    `,
+    `
+      <template>
+        <div>
+          <label
+            for="test"
+            class="label"
+          >Foo</label>
+          <input id="test">
+        </div>
+      </template>
+    `,
+    `
+      <template>
+        <div>
+          <label
+            for="test"
+            class="label"
+          >Foo
+          </label>
+          <input id="test">
+        </div>
+      </template>
+    `,
+    `
+      <template>
+        <div>
+          <label
+            for="test"
+            class="label"
+          >
+            Foo
+          </label>
+          <input id="test">
+        </div>
+      </template>
+    `,
     `
       <template>
         <div>
@@ -61,9 +126,13 @@ tester.run('multiline-html-element-content-newline', rule, {
             content
           </div>
         </div>
-      </template>`,
-    `<div>multiline end tag</div
-      >`,
+      </template>
+    `,
+    `
+      <div>multiline end tag</div
+      >
+    `,
+
     // empty
     `<template><div class="panel"></div></template>`,
     `
@@ -71,7 +140,9 @@ tester.run('multiline-html-element-content-newline', rule, {
         <div
           class="panel">
         </div>
-      </template>`,
+      </template>
+    `,
+
     // allowEmptyLines
     {
       code: `
@@ -109,11 +180,14 @@ tester.run('multiline-html-element-content-newline', rule, {
         </template>`,
       options: [{ allowEmptyLines: true }]
     },
+
     // self closing
     `
       <template>
         <self-closing />
-      </template>`,
+      </template>
+    `,
+
     // ignores
     `
       <template>
@@ -180,6 +254,7 @@ tester.run('multiline-html-element-content-newline', rule, {
         ignores: ['IgnoreTag']
       }]
     },
+
     // Ignore if no closing brackets
     `
       <template>
diff --git a/tests/lib/rules/no-async-in-computed-properties.js b/tests/lib/rules/no-async-in-computed-properties.js
index 39cef9f9..cf886c7e 100644
--- a/tests/lib/rules/no-async-in-computed-properties.js
+++ b/tests/lib/rules/no-async-in-computed-properties.js
@@ -25,6 +25,19 @@ const ruleTester = new RuleTester()
 ruleTester.run('no-async-in-computed-properties', rule, {
 
   valid: [
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          computed: {
+            foo: function () {
+              return;
+            },
+          }
+        }
+      `,
+      parserOptions
+    },
     {
       filename: 'test.vue',
       code: `
diff --git a/tests/lib/rules/no-boolean-default.js b/tests/lib/rules/no-boolean-default.js
new file mode 100644
index 00000000..c113514b
--- /dev/null
+++ b/tests/lib/rules/no-boolean-default.js
@@ -0,0 +1,310 @@
+/**
+ * @fileoverview Prevents boolean defaults from being set
+ * @author Hiroki Osame
+ */
+'use strict'
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require('../../../lib/rules/no-boolean-default')
+
+var RuleTester = require('eslint').RuleTester
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+var ruleTester = new RuleTester({
+  parserOptions: {
+    ecmaVersion: 2018,
+    sourceType: 'module'
+  }
+})
+ruleTester.run('no-boolean-default', rule, {
+
+  valid: [
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            enabled: Boolean
+          }
+        }
+      `
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            enabled: Boolean
+          }
+        }
+      `,
+      options: ['no-default']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            enabled: Boolean
+          }
+        }
+      `,
+      options: ['default-false']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const props = {};
+        export default {
+          props: {
+            ...props,
+            enabled: Boolean
+          }
+        }
+      `
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const props = {};
+        export default {
+          props: {
+            ...props,
+            enabled: Boolean
+          }
+        }
+      `,
+      options: ['no-default']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const props = {};
+        export default {
+          props: {
+            ...props,
+            enabled: Boolean
+          }
+        }
+      `,
+      options: ['default-false']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              ...data
+            }
+          }
+        }
+      `
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              ...data
+            }
+          }
+        }
+      `,
+      options: ['no-default']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              ...data
+            }
+          }
+        }
+      `,
+      options: ['default-false']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              default: false,
+              ...data
+            }
+          }
+        }
+      `,
+      options: ['default-false']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: data
+          }
+        }
+      `
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: data
+          }
+        }
+      `,
+      options: ['no-default']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: data
+          }
+        }
+      `,
+      options: ['default-false']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: {
+              ...data
+            }
+          }
+        }
+      `
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: {
+              ...data
+            }
+          }
+        }
+      `,
+      options: ['no-default']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: {
+              ...data
+            }
+          }
+        }
+      `,
+      options: ['default-false']
+    }
+  ],
+
+  invalid: [
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              default: true,
+            }
+          }
+        }
+      `,
+      options: ['default-false'],
+      errors: [{
+        message: 'Boolean prop should only be defaulted to false.',
+        line: 6
+      }]
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              default: null,
+            }
+          }
+        }
+      `,
+      options: ['default-false'],
+      errors: [{
+        message: 'Boolean prop should only be defaulted to false.',
+        line: 6
+      }]
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              default: false,
+            }
+          }
+        }
+      `,
+      options: ['no-default'],
+      errors: [{
+        message: 'Boolean prop should not set a default (Vue defaults it to false).',
+        line: 6
+      }]
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              default: true,
+            }
+          }
+        }
+      `,
+      options: ['no-default'],
+      errors: [{
+        message: 'Boolean prop should not set a default (Vue defaults it to false).',
+        line: 6
+      }]
+    }
+  ]
+})
diff --git a/tests/lib/rules/no-duplicate-attributes.js b/tests/lib/rules/no-duplicate-attributes.js
index 03cd71c7..aeef7fa8 100644
--- a/tests/lib/rules/no-duplicate-attributes.js
+++ b/tests/lib/rules/no-duplicate-attributes.js
@@ -52,6 +52,14 @@ tester.run('no-duplicate-attributes', rule, {
       filename: 'test.vue',
       code: '<template><div><div :style="a" style="b"></div></div></template>',
       options: [{ allowCoexistStyle: true }]
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><my-component foo :[foo]></my-component></template>'
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><my-component :foo :[foo]></my-component></template>'
     }
   ],
   invalid: [
diff --git a/tests/lib/rules/no-empty-pattern.js b/tests/lib/rules/no-empty-pattern.js
new file mode 100644
index 00000000..480cee7b
--- /dev/null
+++ b/tests/lib/rules/no-empty-pattern.js
@@ -0,0 +1,252 @@
+/**
+ * @author Yosuke Ota
+ */
+'use strict'
+
+const RuleTester = require('eslint').RuleTester
+const rule = require('../../../lib/rules/no-empty-pattern')
+
+const tester = new RuleTester({
+  parser: 'vue-eslint-parser',
+  parserOptions: { ecmaVersion: 2018 }
+})
+
+tester.run('no-empty-pattern', rule, {
+  valid: [
+    `<template>
+      <div
+        @attr="() => {
+          var {a = {}} = foo;
+          var {a = []} = foo;
+        }"
+      />
+    </template>`,
+    `<template>
+      <div
+        @attr="function foo({a = {}}) {}"
+      />
+    </template>`,
+    `<template>
+      <div
+        @attr="function foo({a = []}) {}"
+      />
+    </template>`,
+    `<template>
+      <div
+        @attr="({a = {}}) => a"
+      />
+    </template>`,
+    `<template>
+      <div
+        @attr="({a = []}) => a"
+      />
+    </template>`,
+    `<template>
+      <div
+        slot-scope="{a = []}"
+      />
+    </template>`
+  ],
+  invalid: [
+    {
+      code: `
+      <template>
+        <div
+          @attr="() => {
+            var {} = foo;
+            var [] = foo;
+            var {a: {}} = foo;
+            var {a: []} = foo;
+          }"
+        />
+      </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty object pattern.',
+          line: 5
+        },
+        {
+          message: 'Unexpected empty array pattern.',
+          line: 6
+        },
+        {
+          message: 'Unexpected empty object pattern.',
+          line: 7
+        },
+        {
+          message: 'Unexpected empty array pattern.',
+          line: 8
+        }
+      ]
+    },
+    {
+      code: `
+        <template>
+          <div
+            @attr="function foo({}) {}"
+          />
+        </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty object pattern.',
+          line: 4
+        }
+      ]
+    },
+    {
+      code: `
+        <template>
+          <div
+            @attr="function foo([]) {}"
+          />
+        </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty array pattern.',
+          line: 4
+        }
+      ]
+    },
+    {
+      code: `
+        <template>
+          <div
+            @attr="function foo({a: {}}) {}"
+          />
+        </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty object pattern.',
+          line: 4
+        }
+      ]
+    },
+    {
+      code: `
+        <template>
+          <div
+            @attr="function foo({a: []}) {}"
+          />
+        </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty array pattern.',
+          line: 4
+        }
+      ]
+    },
+    {
+      code: `
+        <template>
+          <div
+            @attr="({}) => foo()"
+          />
+        </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty object pattern.',
+          line: 4
+        }
+      ]
+    },
+    {
+      code: `
+        <template>
+          <div
+            @attr="([]) => foo()"
+          />
+        </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty array pattern.',
+          line: 4
+        }
+      ]
+    },
+    {
+      code: `
+        <template>
+          <div
+            @attr="({a: {}}) => a"
+          />
+        </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty object pattern.',
+          line: 4
+        }
+      ]
+    },
+    {
+      code: `
+        <template>
+          <div
+            @attr="({a: []}) => a"
+          />
+        </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty array pattern.',
+          line: 4
+        }
+      ]
+    },
+    {
+      code: `
+      <template>
+        <div
+          slot-scope="{}"
+        />
+      </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty object pattern.',
+          line: 4
+        }
+      ]
+    },
+    {
+      code: `
+      <template>
+        <div
+          slot-scope="[]"
+        />
+      </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty array pattern.',
+          line: 4
+        }
+      ]
+    },
+    {
+      code: `
+      <template>
+        <div
+          slot-scope="{a: {}}"
+        />
+      </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty object pattern.',
+          line: 4
+        }
+      ]
+    },
+    {
+      code: `
+      <template>
+        <div
+          slot-scope="{a: []}"
+        />
+      </template>`,
+      errors: [
+        {
+          message: 'Unexpected empty array pattern.',
+          line: 4
+        }
+      ]
+    }
+
+  ]
+})
diff --git a/tests/lib/rules/no-multi-spaces.js b/tests/lib/rules/no-multi-spaces.js
index 68433af4..225f81c0 100644
--- a/tests/lib/rules/no-multi-spaces.js
+++ b/tests/lib/rules/no-multi-spaces.js
@@ -118,8 +118,8 @@ ruleTester.run('no-multi-spaces', rule, {
       output: '<template><div :class="foo" /></template>',
       errors: [
         {
-          message: "Multiple spaces found before ':class'.",
-          type: 'HTMLIdentifier'
+          message: "Multiple spaces found before ':'.",
+          type: 'Punctuator'
         },
         {
           message: "Multiple spaces found before '/>'.",
diff --git a/tests/lib/rules/no-restricted-syntax.js b/tests/lib/rules/no-restricted-syntax.js
index 3fcdbc24..36d7b9a0 100644
--- a/tests/lib/rules/no-restricted-syntax.js
+++ b/tests/lib/rules/no-restricted-syntax.js
@@ -24,6 +24,18 @@ tester.run('no-restricted-syntax', rule, {
           'message': 'Call expressions are not allowed.'
         }
       ]
+    },
+    {
+      code: `
+        <template>
+          <input :[value]="value">
+        </template>`,
+      options: [
+        {
+          'selector': 'CallExpression',
+          'message': 'Call expressions are not allowed.'
+        }
+      ]
     }
   ],
   invalid: [
@@ -113,6 +125,20 @@ tester.run('no-restricted-syntax', rule, {
           endColumn: 53
         }
       ]
+    },
+
+    {
+      code: `
+        <template>
+          <input :[fn()]="fn()">
+        </template>`,
+      options: [
+        {
+          'selector': 'CallExpression',
+          'message': 'Call expressions are not allowed.'
+        }
+      ],
+      errors: ['Call expressions are not allowed.', 'Call expressions are not allowed.']
     }
   ]
 })
diff --git a/tests/lib/rules/no-unused-components.js b/tests/lib/rules/no-unused-components.js
index f62b83fb..a0362597 100644
--- a/tests/lib/rules/no-unused-components.js
+++ b/tests/lib/rules/no-unused-components.js
@@ -411,6 +411,66 @@ tester.run('no-unused-components', rule, {
           }
         }
       </script>`
+    },
+
+    // empty `:is`
+    {
+      filename: 'test.vue',
+      code: `
+      <template>
+        <component :is=""></component>
+      </template>`
+    },
+    {
+      filename: 'test.vue',
+      code: `
+      <template>
+        <component :is></component>
+      </template>`
+    },
+
+    // computed properties
+    {
+      filename: 'test.vue',
+      code: `
+      <template>
+        <div />
+      </template>
+      <script>
+        export default {
+          components: {
+            [foo.bar]: baz
+          }
+        }
+      </script>`
+    },
+    {
+      filename: 'test.vue',
+      code: `
+      <template>
+        <div />
+      </template>
+      <script>
+        export default {
+          components: {
+            [foo]: Bar
+          }
+        }
+      </script>`
+    },
+    {
+      filename: 'test.vue',
+      code: `
+      <template>
+        <foo />
+      </template>
+      <script>
+        export default {
+          components: {
+            ['foo']: Foo
+          }
+        }
+      </script>`
     }
   ],
   invalid: [
@@ -512,6 +572,78 @@ tester.run('no-unused-components', rule, {
         message: 'The "Bar" component has been registered but not used.',
         line: 14
       }]
+    },
+
+    // empty `:is`
+    {
+      filename: 'test.vue',
+      code: `
+      <template>
+        <component :is=""></component>
+      </template>
+      <script>
+        export default {
+          components: {
+            Foo,
+          },
+        }
+      </script>`,
+      errors: [{
+        message: 'The "Foo" component has been registered but not used.',
+        line: 8
+      }]
+    },
+    {
+      filename: 'test.vue',
+      code: `
+      <template>
+        <component :is></component>
+      </template>
+      <script>
+        export default {
+          components: {
+            Foo,
+          },
+        }
+      </script>`,
+      errors: [{
+        message: 'The "Foo" component has been registered but not used.',
+        line: 8
+      }]
+    },
+
+    // computed properties
+    {
+      filename: 'test.vue',
+      code: `
+      <template>
+        <div />
+      </template>
+      <script>
+        export default {
+          components: {
+            ['foo']: Foo,
+            [\`bar\`]: Bar,
+            ['baz']: Baz,
+            [qux]: Qux,
+            ...components,
+            quux,
+          }
+        }
+      </script>`,
+      errors: [{
+        message: 'The "foo" component has been registered but not used.',
+        line: 8
+      }, {
+        message: 'The "bar" component has been registered but not used.',
+        line: 9
+      }, {
+        message: 'The "baz" component has been registered but not used.',
+        line: 10
+      }, {
+        message: 'The "quux" component has been registered but not used.',
+        line: 13
+      }]
     }
   ]
 })
diff --git a/tests/lib/rules/no-unused-vars.js b/tests/lib/rules/no-unused-vars.js
index f717e7af..663740e9 100644
--- a/tests/lib/rules/no-unused-vars.js
+++ b/tests/lib/rules/no-unused-vars.js
@@ -49,6 +49,9 @@ tester.run('no-unused-vars', rule, {
     },
     {
       code: '<template><div v-for="x in foo">{{value | f(x)}}</div></template>'
+    },
+    {
+      code: '<template><div v-for="x in foo" :[x]></div></template>'
     }
   ],
   invalid: [
diff --git a/tests/lib/rules/object-curly-spacing.js b/tests/lib/rules/object-curly-spacing.js
index bf6cbc8a..6471f3af 100644
--- a/tests/lib/rules/object-curly-spacing.js
+++ b/tests/lib/rules/object-curly-spacing.js
@@ -21,19 +21,27 @@ tester.run('object-curly-spacing', rule, {
     {
       code: '<template><div :attr="{ a: 1 }" /></template>',
       options: ['always']
+    },
+    '<template><div :[{a:1}]="a" /></template>',
+    {
+      code: '<template><div :[{a:1}]="a" /></template>',
+      options: ['always']
     }
   ],
   invalid: [
     {
       code: '<template><div :attr="{ a: 1}" /></template>',
+      output: '<template><div :attr="{a: 1}" /></template>',
       errors: ["There should be no space after '{'."]
     },
     {
       code: '<template><div :attr="{a: 1 }" /></template>',
+      output: '<template><div :attr="{a: 1}" /></template>',
       errors: ["There should be no space before '}'."]
     },
     {
       code: '<template><div :attr="{ a: 1 }" /></template>',
+      output: '<template><div :attr="{a: 1}" /></template>',
       errors: [
         "There should be no space after '{'.",
         "There should be no space before '}'."
@@ -42,16 +50,19 @@ tester.run('object-curly-spacing', rule, {
     {
       code: '<template><div :attr="{ a: 1}" /></template>',
       options: ['never'],
+      output: '<template><div :attr="{a: 1}" /></template>',
       errors: ["There should be no space after '{'."]
     },
     {
       code: '<template><div :attr="{a: 1 }" /></template>',
       options: ['never'],
+      output: '<template><div :attr="{a: 1}" /></template>',
       errors: ["There should be no space before '}'."]
     },
     {
       code: '<template><div :attr="{ a: 1 }" /></template>',
       options: ['never'],
+      output: '<template><div :attr="{a: 1}" /></template>',
       errors: [
         "There should be no space after '{'.",
         "There should be no space before '}'."
@@ -60,16 +71,28 @@ tester.run('object-curly-spacing', rule, {
     {
       code: '<template><div :attr="{ a: 1}" /></template>',
       options: ['always'],
+      output: '<template><div :attr="{ a: 1 }" /></template>',
       errors: ["A space is required before '}'."]
     },
     {
       code: '<template><div :attr="{a: 1 }" /></template>',
       options: ['always'],
+      output: '<template><div :attr="{ a: 1 }" /></template>',
       errors: ["A space is required after '{'."]
     },
     {
       code: '<template><div :attr="{a: 1}" /></template>',
       options: ['always'],
+      output: '<template><div :attr="{ a: 1 }" /></template>',
+      errors: [
+        "A space is required after '{'.",
+        "A space is required before '}'."
+      ]
+    },
+    {
+      code: '<template><div :[{a:1}]="{a:1}" /></template>',
+      options: ['always'],
+      output: '<template><div :[{a:1}]="{ a:1 }" /></template>',
       errors: [
         "A space is required after '{'.",
         "A space is required before '}'."
diff --git a/tests/lib/rules/require-default-prop.js b/tests/lib/rules/require-default-prop.js
index 43d88ed5..84aca170 100644
--- a/tests/lib/rules/require-default-prop.js
+++ b/tests/lib/rules/require-default-prop.js
@@ -231,6 +231,57 @@ ruleTester.run('require-default-prop', rule, {
         message: `Prop 'a' requires default value to be set.`,
         line: 4
       }]
+    },
+
+    // computed propertys
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            a: String,
+            'b': String,
+            ['c']: String,
+            [\`d\`]: String,
+          }
+        };
+      `,
+      errors: [{
+        message: `Prop 'a' requires default value to be set.`,
+        line: 4
+      }, {
+        message: `Prop 'b' requires default value to be set.`,
+        line: 5
+      }, {
+        message: `Prop 'c' requires default value to be set.`,
+        line: 6
+      }, {
+        message: `Prop 'd' requires default value to be set.`,
+        line: 7
+      }]
+    },
+    // unknown static name
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            [foo]: String,
+            [bar()]: String,
+            [baz.baz]: String,
+          }
+        };
+      `,
+      errors: [{
+        message: `Prop '[foo]' requires default value to be set.`,
+        line: 4
+      }, {
+        message: `Prop '[bar()]' requires default value to be set.`,
+        line: 5
+      }, {
+        message: `Prop '[baz.baz]' requires default value to be set.`,
+        line: 6
+      }]
     }
   ]
 })
diff --git a/tests/lib/rules/require-valid-default-prop.js b/tests/lib/rules/require-valid-default-prop.js
index 4d434f2a..dd9931cb 100644
--- a/tests/lib/rules/require-valid-default-prop.js
+++ b/tests/lib/rules/require-valid-default-prop.js
@@ -444,6 +444,37 @@ ruleTester.run('require-valid-default-prop', rule, {
       parserOptions: { ecmaVersion: 6, sourceType: 'module' },
       parser: 'typescript-eslint-parser',
       errors: errorMessage('function or number')
+    },
+
+    {
+      filename: 'test.vue',
+      code: `export default {
+        props: {
+          'foo': {
+            type: Object,
+            default: ''
+          },
+          ['bar']: {
+            type: Object,
+            default: ''
+          },
+          [baz]: {
+            type: Object,
+            default: ''
+          }
+        }
+      }`,
+      parserOptions,
+      errors: [{
+        message: `Type of the default value for 'foo' prop must be a function.`,
+        line: 5
+      }, {
+        message: `Type of the default value for 'bar' prop must be a function.`,
+        line: 9
+      }, {
+        message: `Type of the default value for '[baz]' prop must be a function.`,
+        line: 13
+      }]
     }
   ]
 })
diff --git a/tests/lib/rules/singleline-html-element-content-newline.js b/tests/lib/rules/singleline-html-element-content-newline.js
index 679e4868..bc4c0af9 100644
--- a/tests/lib/rules/singleline-html-element-content-newline.js
+++ b/tests/lib/rules/singleline-html-element-content-newline.js
@@ -33,39 +33,59 @@ tester.run('singleline-html-element-content-newline', rule, {
         <div class="panel">
           content
         </div>
-      </template>`,
+      </template>
+    `,
     `
       <template>
         <div class="panel">
           <div>
           </div>
         </div>
-      </template>`,
+      </template>
+    `,
     `
       <template>
         <div class="panel">
           <!-- comment -->
         </div>
-      </template>`,
+      </template>
+    `,
     `
       <template>
         <div>
           content
         </div>
-      </template>`,
+      </template>
+    `,
     `
       <template>
         <div>
           <div>
           </div>
         </div>
-      </template>`,
+      </template>
+    `,
     `
       <template>
         <div>
           <!-- comment -->
         </div>
-      </template>`,
+      </template>
+    `,
+    `
+      <template>
+        <a href="/">Home</a>
+      </template>
+    `,
+    `
+      <template>
+        <form>
+          <label for="test">Home</label>
+          <input id="test" name="test">
+        </form>
+      </template>
+    `,
+
     // ignoreWhenNoAttributes: true
     `
       <template>
@@ -91,6 +111,7 @@ tester.run('singleline-html-element-content-newline', rule, {
       <template>
         <div>    </div>
       </template>`,
+
     // ignoreWhenNoAttributes: false
     {
       code: `
diff --git a/tests/lib/rules/space-infix-ops.js b/tests/lib/rules/space-infix-ops.js
index ba67575f..2c3da144 100644
--- a/tests/lib/rules/space-infix-ops.js
+++ b/tests/lib/rules/space-infix-ops.js
@@ -19,20 +19,29 @@ const message = semver.lt(CLIEngine.version, '5.10.0')
 tester.run('space-infix-ops', rule, {
   valid: [
     '<template><div :attr="a + 1" /></template>',
-    '<template><div :attr="a ? 1 : 2" /></template>'
+    '<template><div :attr="a ? 1 : 2" /></template>',
+    '<template><div :[1+2]="a" /></template>'
   ],
   invalid: [
     {
       code: '<template><div :attr="a+1" /></template>',
+      output: '<template><div :attr="a + 1" /></template>',
       errors: [message('+')]
     },
     {
       code: '<template><div :attr="a?1 : 2" /></template>',
+      output: '<template><div :attr="a ? 1 : 2" /></template>',
       errors: [message('?')]
     },
     {
       code: '<template><div :attr="a ? 1:2" /></template>',
+      output: '<template><div :attr="a ? 1 : 2" /></template>',
       errors: [message(':')]
+    },
+    {
+      code: '<template><div :[1+2]="1+2" /></template>',
+      output: '<template><div :[1+2]="1 + 2" /></template>',
+      errors: [message('+')]
     }
   ]
 })
diff --git a/tests/lib/rules/space-unary-ops.js b/tests/lib/rules/space-unary-ops.js
index 2f36302b..f6accb20 100644
--- a/tests/lib/rules/space-unary-ops.js
+++ b/tests/lib/rules/space-unary-ops.js
@@ -14,16 +14,38 @@ const tester = new RuleTester({
 tester.run('space-unary-ops', rule, {
   valid: [
     '<template><div :attr="-a" /></template>',
-    '<template><div :attr="typeof a" /></template>'
+    '<template><div :attr="typeof a" /></template>',
+    '<template><div :[typeof(a)]="a" /></template>',
+    {
+      code: '<template><div :attr="! a" /></template>',
+      options: [{ nonwords: true }]
+    },
+    {
+      code: '<template><div :[!a]="a" /></template>',
+      options: [{ nonwords: true }]
+    }
   ],
   invalid: [
     {
       code: '<template><div :attr="- a" /></template>',
+      output: '<template><div :attr="-a" /></template>',
       errors: ['Unexpected space after unary operator \'-\'.']
     },
     {
       code: '<template><div :attr="typeof(a)" /></template>',
+      output: '<template><div :attr="typeof (a)" /></template>',
       errors: ['Unary word operator \'typeof\' must be followed by whitespace.']
+    },
+    {
+      code: '<template><div :[typeof(a)]="typeof(a)" /></template>',
+      output: '<template><div :[typeof(a)]="typeof (a)" /></template>',
+      errors: ['Unary word operator \'typeof\' must be followed by whitespace.']
+    },
+    {
+      code: '<template><div :[!a]="!a" /></template>',
+      options: [{ nonwords: true }],
+      output: '<template><div :[!a]="! a" /></template>',
+      errors: ['Unary operator \'!\' must be followed by whitespace.']
     }
   ]
 })
diff --git a/tests/lib/rules/this-in-template.js b/tests/lib/rules/this-in-template.js
index 1f7c7c69..29488294 100644
--- a/tests/lib/rules/this-in-template.js
+++ b/tests/lib/rules/this-in-template.js
@@ -106,6 +106,12 @@ function createValidTests (prefix, options) {
         </div>
       </template><!-- ${comment} -->`,
       options
+    },
+
+    // We cannot use `.` in dynamic arguments because the right of the `.` becomes a modifier.
+    {
+      code: `<template><div v-on:[x]="1"></div></template><!-- ${comment} -->`,
+      options
     }
   ]
 }
@@ -153,6 +159,13 @@ function createInvalidTests (prefix, options, message, type) {
       errors: [{ message, type }],
       options
     }
+
+    // We cannot use `.` in dynamic arguments because the right of the `.` becomes a modifier.
+    // {
+    //   code: `<template><div v-on:[${prefix}name]="1"></div></template><!-- ${comment} -->`,
+    //   errors: [{ message, type }],
+    //   options
+    // }
   ].concat(options[0] === 'always'
     ? []
     : [
diff --git a/tests/lib/rules/use-v-on-exact.js b/tests/lib/rules/use-v-on-exact.js
index be90196b..2bb99040 100644
--- a/tests/lib/rules/use-v-on-exact.js
+++ b/tests/lib/rules/use-v-on-exact.js
@@ -152,6 +152,12 @@ ruleTester.run('use-v-on-exact', rule, {
     },
     {
       code: `<template><UiButton @click.native.stop="foo" @click.native.prevent="bar" /></template>`
+    },
+    {
+      code: `<template><button @[click]="foo"/></template>`
+    },
+    {
+      code: `<template><button @[foo]="foo" @[bar].ctrl="bar"/></template>`
     }
   ],
 
@@ -272,6 +278,17 @@ ruleTester.run('use-v-on-exact', rule, {
         { message: "Consider to use '.exact' modifier.", line: 3 },
         { message: "Consider to use '.exact' modifier.", line: 4 }
       ]
+    },
+    {
+      code: `<template>
+        <button
+          @[foo]="foo"
+          @[foo].ctrl="bar"
+        />
+      </template>`,
+      errors: [
+        { message: "Consider to use '.exact' modifier.", line: 3 }
+      ]
     }
   ]
 })
diff --git a/tests/lib/rules/v-bind-style.js b/tests/lib/rules/v-bind-style.js
index eeab4b9a..bc9afb97 100644
--- a/tests/lib/rules/v-bind-style.js
+++ b/tests/lib/rules/v-bind-style.js
@@ -44,6 +44,26 @@ tester.run('v-bind-style', rule, {
       filename: 'test.vue',
       code: '<template><div v-bind:foo="foo"></div></template>',
       options: ['longform']
+    },
+
+    // Don't enforce `.prop` shorthand because of experimental.
+    {
+      filename: 'test.vue',
+      code: '<template><div :foo.prop="foo"></div></template>'
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div .foo="foo"></div></template>'
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div :foo.prop="foo"></div></template>',
+      options: ['shorthand']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div .foo="foo"></div></template>',
+      options: ['shorthand']
     }
   ],
   invalid: [
@@ -66,6 +86,34 @@ tester.run('v-bind-style', rule, {
       code: '<template><div :foo="foo"></div></template>',
       output: '<template><div v-bind:foo="foo"></div></template>',
       errors: ["Expected 'v-bind' before ':'."]
+    },
+    {
+      filename: 'test.vue',
+      options: ['longform'],
+      code: '<template><div .foo="foo"></div></template>',
+      output: '<template><div v-bind:foo.prop="foo"></div></template>',
+      errors: ["Expected 'v-bind:' instead of '.'."]
+    },
+    {
+      filename: 'test.vue',
+      options: ['longform'],
+      code: '<template><div .foo.sync="foo"></div></template>',
+      output: '<template><div v-bind:foo.prop.sync="foo"></div></template>',
+      errors: ["Expected 'v-bind:' instead of '.'."]
+    },
+    {
+      filename: 'test.vue',
+      options: ['longform'],
+      code: '<template><div .foo.prop="foo"></div></template>',
+      output: '<template><div v-bind:foo.prop="foo"></div></template>',
+      errors: ["Expected 'v-bind:' instead of '.'."]
+    },
+    {
+      filename: 'test.vue',
+      options: ['longform'],
+      code: '<template><div .foo.sync.prop="foo"></div></template>',
+      output: '<template><div v-bind:foo.sync.prop="foo"></div></template>',
+      errors: ["Expected 'v-bind:' instead of '.'."]
     }
   ]
 })
diff --git a/tests/lib/rules/v-on-function-call.js b/tests/lib/rules/v-on-function-call.js
new file mode 100644
index 00000000..cfcbc005
--- /dev/null
+++ b/tests/lib/rules/v-on-function-call.js
@@ -0,0 +1,72 @@
+/**
+ * @author Niklas Higi
+ */
+'use strict'
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+const RuleTester = require('eslint').RuleTester
+const rule = require('../../../lib/rules/v-on-function-call')
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+const tester = new RuleTester({
+  parser: 'vue-eslint-parser',
+  parserOptions: { ecmaVersion: 2015 }
+})
+
+tester.run('v-on-function-call', rule, {
+  valid: [
+    {
+      filename: 'test.vue',
+      code: ''
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo(123)"></div></template>',
+      options: ['always']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo(123)"></div></template>',
+      options: ['never']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo()"></div></template>',
+      options: ['always']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo"></div></template>',
+      options: ['never']
+    }
+  ],
+  invalid: [
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo"></div></template>',
+      output: `<template><div @click="foo"></div></template>`,
+      errors: ["Method calls inside of 'v-on' directives must have parentheses."],
+      options: ['always']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo()"></div></template>',
+      output: `<template><div @click="foo"></div></template>`,
+      errors: ["Method calls without arguments inside of 'v-on' directives must not have parentheses."],
+      options: ['never']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo( )"></div></template>',
+      output: `<template><div @click="foo"></div></template>`,
+      errors: ["Method calls without arguments inside of 'v-on' directives must not have parentheses."],
+      options: ['never']
+    }
+  ]
+})
diff --git a/tests/lib/utils/index.js b/tests/lib/utils/index.js
index 0b8c07e2..f698a98e 100644
--- a/tests/lib/utils/index.js
+++ b/tests/lib/utils/index.js
@@ -246,6 +246,25 @@ describe('getRegisteredComponents', () => {
       ['PrimaryButton', 'secondaryButton', 'the-modal', 'the_dropdown', 'the_input', 'SomeComponent'],
     )
   })
+
+  it('should return an array of only components whose names can be identified', () => {
+    node = parse(`const test = {
+      name: 'test',
+      components: {
+        ...test,
+        Foo,
+        [bar]: Bar,
+        [baz.baz]: Baz,
+        [\`\${qux}\`]: Qux,
+        [\`Quux\`]: Quux
+      }
+    }`)
+
+    assert.deepEqual(
+      utils.getRegisteredComponents(node).map(c => c.name),
+      ['Foo', 'Quux'],
+    )
+  })
 })
 
 describe('getComponentProps', () => {