Repository: vuejs/vue
Pull request: fix(compiler): set end location for incomplete elements

<!--
Please make sure to read the Pull Request Guidelines:
https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#pull-request-guidelines
-->

<!-- PULL REQUEST TEMPLATE -->
<!-- (Update "[ ]" to "[x]" to check a box) -->

**What kind of change does this PR introduce?** (check at least one)

- [x] Bugfix
- [ ] Feature
- [ ] Code style update
- [ ] Refactor
- [ ] Build-related changes
- [ ] Other, please describe:

**Does this PR introduce a breaking change?** (check one)

- [ ] Yes
- [x] No

If yes, please describe the impact and migration path for existing applications:

**The PR fulfills these requirements:**

- [x] It's submitted to the `dev` branch for v2.x (or to a previous version branch), _not_ the `master` branch
- [x] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix #xxx[,#xxx]`, where "xxx" is the issue number)
- [x] All tests are passing: https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#development-setup
- [x] New/updated tests are included

If adding a **new feature**, the PR's description includes:
- [ ] A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)

**Other information:**

End location for incomplete tags are missing, which makes error message looks weird:

```
  tag <incomplete-tag> has no matching end tag.

  2  |  <div>
  3  |    <div>
  4  |      <incomplete-tag>
     |      ^^^^^^^^^^^^^^^^
  5  |    </div>
     |  ^^^^^^^^
  6  |  </div>
     |  ^^^^^^
```

**Expected:**

```
  tag <incomplete-tag> has no matching end tag.

  2  |  <div>
  3  |    <div>
  4  |      <incomplete-tag>
     |      ^^^^^^^^^^^^^^^^
  5  |    </div>
  6  |  </div>
```



Changed files:
filename: src/compiler/parser/html-parser.js
patch: @@ -279,7 +279,7 @@ export function parseHTML (html, options) {
         ) {
           options.warn(
             `tag <${stack[i].tag}> has no matching end tag.`,
-            { start: stack[i].start }
+            { start: stack[i].start, end: stack[i].end }
           )
         }
         if (options.end) {

filename: src/compiler/parser/index.js
patch: @@ -210,7 +210,7 @@ export function parse (
     shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref,
     shouldKeepComment: options.comments,
     outputSourceRange: options.outputSourceRange,
-    start (tag, attrs, unary, start) {
+    start (tag, attrs, unary, start, end) {
       // check namespace.
       // inherit parent ns if there is one
       const ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag)
@@ -229,6 +229,7 @@ export function parse (
       if (process.env.NODE_ENV !== 'production') {
         if (options.outputSourceRange) {
           element.start = start
+          element.end = end
           element.rawAttrsMap = element.attrsList.reduce((cumulated, attr) => {
             cumulated[attr.name] = attr
             return cumulated

filename: test/unit/modules/compiler/compiler-options.spec.js
patch: @@ -140,6 +140,11 @@ describe('compile options', () => {
     expect(compiled.errors[0].end).toBe(17)
     expect(compiled.errors[1].start).toBe(18)
     expect(compiled.errors[1].end).toBe(29)
+
+    compiled = compile('<div><span></div>', { outputSourceRange: true })
+    expect(compiled.errors.length).toBe(1)
+    expect(compiled.errors[0].start).toBe(5)
+    expect(compiled.errors[0].end).toBe(11)
   })
 
   it('should collect source range for binding keys', () => {